```python
def retry_delays(attempts, base, cap):
    if isinstance(attempts, bool) or not isinstance(attempts, int):
        raise TypeError("attempts must be a non-negative integer")
    if attempts < 0:
        raise ValueError("attempts must be non-negative")
    if base < 0:
        raise ValueError("base must be non-negative")
    if cap < 0:
        raise ValueError("cap must be non-negative")
    
    result = []
    for i in range(attempts):
        # Compute base * 2**i carefully to avoid overflow
        # If base is 0, delay is 0
        if base == 0:
            delay = 0
        else:
            # Check if base * 2**i would exceed cap
            # We can compare using logarithms or incremental multiplication
            # To avoid overflow, we can check if 2**i * base > cap
            # Since cap is non-negative, if base * 2**i >= cap, use cap
            # We need to avoid computing 2**i as a huge int then converting to float
            
            # Use incremental approach: start with base, multiply by 2 each step
            # But we need to handle the case where base * 2**i might overflow float
            
            # Better approach: compute delay incrementally
            # delay_i = min(cap, base * 2**i)
            # We can track current_delay = base * 2**i incrementally
            
            # Let's use a different approach: compute the value step by step
            # current = base
            # for each i, delay = min(cap, current), then current *= 2
            
            # But we need to handle overflow when current becomes too large
            # If current > cap, then min(cap, current) = cap, and we can just append cap
            
            # Let's restructure:
            current = base
            for i in range(attempts):
                if current > cap:
                    delay = cap
                else:
                    delay = current
                result.append(delay)
                current *= 2
                # If current becomes too large for float, we can detect it
                # But since we're comparing with cap (a float), and current is a float,
                # we need to be careful. If base is an int, current starts as int.
                # Multiplying int by 2 repeatedly can create huge ints.
                # We should convert to float or handle carefully.
                
                # Actually, let's ensure current is handled properly.
                # If base is int, current is int. 2**i as int can be huge.
                # But we're comparing current > cap where cap is float.
                # Python can compare int and float, but if int is too large,
                # converting to float for comparison might overflow.
                
                # Safer: if current is an int and very large, we know it's > cap
                # because cap is a float (non-negative). If current > some threshold,
                # it's definitely > cap.
                
                # Let's check: if current is int and current > cap, we can just use cap.
                # But comparing huge int to float might cause OverflowError.
                
                # Alternative: use logarithms to check if base * 2**i > cap
                # log2(base * 2**i) = log2(base) + i
                # If log2(base) + i > log2(cap), then base * 2**i > cap
                
                # But base could be 0, which we already handled.
                # If base > 0 and cap > 0, we can use logs.
                # If cap == 0, then delay is always 0 (since base >= 0, min(0, ...) = 0).
                
                # Let's handle cap == 0 separately.
                pass
        
    # Let me rewrite more carefully
    result = []
    if cap == 0:
        return [0] * attempts
    
    if base == 0:
        return [0] * attempts
    
    # base > 0, cap > 0
    # We need to compute min(cap, base * 2**i) for i in range(attempts)
    # To avoid overflow, we can use logarithms to determine when base * 2**i > cap
    
    import math
    log_base = math.log2(base)
    log_cap = math.log2(cap)
    
    for i in range(attempts):
        # base * 2**i > cap iff log2(base) + i > log2(cap)
        if log_base + i > log_cap:
            delay = cap
        else:
            delay = base * (2 ** i)
        result.append(delay)
    
    return result
```