```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
            # To check this without overflow:
            # If base == 0, handled above
            # If cap == 0, delay is 0
            if cap == 0:
                delay = 0
            else:
                # Check if base * 2**i > cap
                # We can compute 2**i as int, then multiply by base
                # But base might be float, so base * 2**i could overflow when converting 2**i to float
                
                # Better approach: 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 if value exceeds cap
                # Start with val = base, multiply by 2 each step, but cap the value
                
                # Actually, let's compute iteratively to avoid huge numbers
                # val = base * 2**i, but we can compute it incrementally
                # val starts at base, each step val *= 2, but if val > cap, use cap
                
                # Let's use an iterative approach
                pass
        
        # Let me redo this properly with an iterative approach
        # Reset and use iterative computation
        result.append(delay)
    
    # Redo properly
    result = []
    val = base
    for i in range(attempts):
        if val > cap:
            result.append(cap)
        else:
            result.append(val)
        val *= 2
        # If val already exceeds cap, subsequent values will also exceed cap
        # But we still need to append cap for remaining iterations
        # Actually, once val > cap, all subsequent delays are cap
        # But we need to be careful: val might overflow if we keep multiplying
    
    # Hmm, the iterative approach has the same overflow issue if val becomes huge
    # Let me think again
    
    # The key insight: once base * 2**i > cap, all subsequent values are cap
    # So we can stop computing the actual value and just append cap
    
    # But we need to detect when base * 2**i > cap without overflow
    
    # Let's use a different approach:
    # For each i, compute min(cap, base * 2**i)
    # If base == 0, all values are 0
    # If cap == 0, all values are 0
    # Otherwise, find the smallest i where base * 2**i > cap
    # For i < that threshold, compute normally
    # For i >= threshold, use cap
    
    # To find the threshold without overflow:
    # base * 2**i > cap
    # 2**i > cap / base
    # i > log2(cap / base)
    
    # But log2 might have precision issues. Let's use integer comparison.
    
    # Actually, let's just compute iteratively but stop when val > cap
    # Once val > cap, all remaining entries are cap
    
    result = []
    val = base
    for i in range(attempts):
        if val > cap:
            result.append(cap)
        else:
            result.append(val)
        val *= 2
        # If val > cap, we can break early and fill with cap
        if val > cap:
            # All remaining entries are cap
            for _ in range(i + 1, attempts):
                result.append(cap)
            break
    
    return result
```