```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 without converting huge int to float
        # If base is 0, delay is 0
        if base == 0:
            delay = 0
        else:
            # Check if base * 2**i exceeds cap
            # We need to compare base * 2**i with cap without overflow
            # If base is an int, base * 2**i is an int, no overflow issue for comparison
            # If base is a float, we need to be careful
            
            # Handle case where base is a float
            if isinstance(base, float):
                # If base * 2**i would overflow float, it means it's > cap (since cap is finite)
                # We can check by comparing in a way that avoids overflow
                # If 2**i is too large for float, then base * 2**i > cap (assuming cap is finite float)
                # But cap could be very large too. Let's think differently.
                
                # Actually, the issue is that 2**i as an int can be huge, and converting to float overflows.
                # We should avoid converting 2**i to float.
                
                # If base is float, we can compute step by step or use logarithms.
                # Simpler: if base * 2**i > cap, return cap. Otherwise compute.
                # To avoid overflow, we can check if 2**i > cap / base (when base > 0)
                # But cap / base might also have issues.
                
                # Let's use a different approach:
                # If base == 0, delay = 0
                # Otherwise, we want min(cap, base * 2**i)
                # If base * 2**i > cap, return cap
                # To check this without overflow:
                # If base > 0 and cap > 0:
                #   if 2**i > cap / base, then base * 2**i > cap
                #   But cap / base could be problematic if base is very small.
                
                # Alternative: use logarithms
                # log2(base * 2**i) = log2(base) + i
                # log2(cap) = log2(cap)
                # If log2(base) + i > log2(cap), then base * 2**i > cap
                
                import math
                if base == 0:
                    delay = 0
                elif cap == 0:
                    delay = 0
                else:
                    # Check if base * 2**i > cap using logs
                    # log2(base) + i > log2(cap)
                    # But base could be 0, handled above
                    # base > 0, cap > 0
                    log_base = math.log2(base)
                    log_cap = math.log2(cap)
                    if log_base + i > log_cap:
                        delay = cap
                    else:
                        delay = base * (2 ** i)
            else:
                # base is int
                # base * 2**i is int, no overflow for comparison
                val = base * (2 ** i)
                if val > cap:
                    delay = cap
                else:
                    delay = val
        result.append(delay)
    return result
```