```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 causing overflow by checking if 2**i would exceed cap/base
        # If base == 0, then base * 2**i == 0, so min(cap, 0) = 0
        if base == 0:
            result.append(0.0)
            continue
        
        # Check if 2**i * base > cap, in which case we use cap
        # To avoid overflow, we can check if 2**i > cap / base
        # But cap / base might be problematic if base is very small.
        # Alternative: compute 2**i as an integer, then multiply by base.
        # If 2**i is too large to convert to float, we know the result exceeds cap (since base > 0).
        # So we can check: if 2**i > cap / base, use cap.
        # However, cap / base could be very large or cause issues.
        
        # Better approach: use logarithms or check if 2**i exceeds a threshold.
        # Since base > 0, if 2**i * base > cap, then 2**i > cap / base.
        # We can compute cap / base as a float, but if base is very small, cap/base could be huge.
        
        # Let's use a different approach: compute 2**i as an integer.
        # If 2**i is too large to convert to float, then base * 2**i > cap (assuming base > 0).
        # So we can check if 2**i > cap / base.
        
        # To avoid overflow, we can check if 2**i > cap / base using integer comparison.
        # But cap and base are floats, so cap / base is a float.
        
        # Alternative: use math.log2 to check if i > log2(cap / base).
        # But we cannot import math.
        
        # Let's try a simpler approach: compute 2**i as an integer.
        # If 2**i is too large to convert to float, we know the result exceeds cap.
        # So we can check if 2**i > cap / base.
        
        # Since base > 0, we can compute cap / base as a float.
        # If 2**i > cap / base, then base * 2**i > cap, so we use cap.
        
        # But 2**i could be very large. We can check if 2**i > cap / base.
        # If cap / base is very large, 2**i might still be smaller.
        
        # Let's use a try-except to handle overflow.
        try:
            power = 2 ** i
            value = base * power
            if value > cap:
                result.append(cap)
            else:
                result.append(value)
        except OverflowError:
            result.append(cap)
    
    return result
```