```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
            # Since cap is a float, we need to handle carefully
            # If 2**i is too large, base * 2**i will definitely exceed cap (if cap is finite)
            # But we need to avoid OverflowError when converting int to float
            
            # Approach: if base * 2**i > cap, use cap
            # We can check if 2**i > cap / base (when base > 0)
            # But cap / base might be problematic if base is very small
            
            # Alternative: compute step by step, checking overflow
            # Or: if i is large enough that 2**i > cap / base, then min(cap, base*2**i) = cap
            
            # Let's think: base * 2**i vs cap
            # If base == 0, handled above
            # If base > 0:
            #   base * 2**i > cap  <=>  2**i > cap / base
            #   So if 2**i > cap / base, result is cap
            #   Otherwise, result is base * 2**i
            
            # But cap / base could be a float, and 2**i is an int
            # We need to compare int 2**i with float cap/base
            # If cap/base is very large, 2**i might overflow when converted to float
            
            # Better approach: use logarithms or iterative multiplication with early exit
            # Or: compute base * 2**i incrementally, but stop when it exceeds cap
            
            # Let's do incremental computation:
            # Start with val = base
            # For each i, val = base * 2**i
            # But we can compute iteratively: val starts at base, then doubles each step
            # If val > cap, we can just append cap for remaining iterations
            
            # Actually, let's restructure:
            # We'll compute iteratively to avoid huge ints
            
            # Hmm, but we're in a loop already. Let me restructure the whole function.
            pass
        
        result.append(delay)
    
    return result
```