```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 2**i as int, then multiply by base
            # But if 2**i is too large, base * 2**i as float will overflow
            
            # Check if base * 2**i > cap without computing the full value
            # If base == 0, handled above
            # If cap == 0, delay is 0
            if cap == 0:
                delay = 0
            else:
                # We need to check if base * 2**i > cap
                # This is equivalent to 2**i > cap / base
                # But cap / base might not be exact for floats
                
                # Alternative: use incremental multiplication with early termination
                # Start with val = base
                # For each i, val = base * 2**i
                # If val > cap, use cap
                
                # Let's compute incrementally
                pass
        
        # Let me redo this more carefully
        # Use incremental computation to avoid overflow
        # current = base * 2**i, but track it as a float
        # If current > cap, use cap
        
        # Actually, let's just compute incrementally
        # We'll track the current delay value
        # Start at i=0: delay = base
        # For i=1: delay = base * 2
        # etc.
        
        # But we need to handle the case where base * 2**i overflows float
        
        # Let's use a helper approach:
        # If base * 2**i > cap, return cap
        # We can check this by seeing if 2**i > cap / base (when base > 0)
        
        # For safety, let's compute incrementally and check for overflow
        # We'll maintain a running value
        
        # Actually, the simplest safe approach:
        # Compute power = 2**i as an integer
        # Then compute base * power
        # If base is a float and power is very large, base * power might overflow
        
        # Let's check: if base * 2**i > cap, use cap
        # We can do this comparison without computing the full product
        
        # If base == 0: delay = 0
        # If cap == 0: delay = 0
        # Otherwise, check if 2**i * base > cap
        
        # For large i, 2**i can be huge. We need to avoid converting huge ints to float.
        
        # Approach: use logarithms
        # log2(base * 2**i) = log2(base) + i
        # 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
            # log2(base * 2**i) = log2(base) + i
            # log2(cap) = log2(cap)
            # If log2(base) + i > log2(cap), use cap
            
            # But we need to be careful with floating point precision
            # Let's compute the actual value if it's safe
            
            # If base * 2**i <= cap, compute it
            # Otherwise, use cap
            
            # Check: is base * 2**i <= cap?
            # This is equivalent to 2**i <= cap / base
            
            # Compute cap / base as a float
            ratio = cap / base
            
            # Check if 2**i <= ratio
            # If i is large, 2**i might be huge
            
            # Use logarithm check
            if i > 0:
                # log2(2**i) = i
                # log2(ratio) = log2(cap / base)
                # If i > log2(ratio), then 2**i > ratio, so base * 2**i > cap
                
                log_ratio = math.log2(ratio) if ratio > 0 else float('inf')
                if i > log_ratio:
                    delay = cap
                else:
                    delay = base * (2 ** i)
            else:
                delay = base
        
        result.append(delay)
    
    return result
```