```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
        # We can avoid computing 2**i as a huge int by comparing incrementally
        # Since cap is non-negative, if base * 2**i > cap, we use cap
        # To avoid overflow, we can check: if 2**i > cap / base, then value = cap
        # But cap / base might be float. Instead, we can use integer comparison carefully.
        
        # Alternative: compute value step by step, but cap the value at cap
        # Start with current = base, and for each i, current = min(cap, current * 2)
        # This avoids huge integers because once current reaches cap, it stays at cap.
        
        # Let's use an iterative approach that caps at cap to prevent overflow
        pass
    
    # Better approach: iterative with capping
    result = []
    current = base
    for i in range(attempts):
        if current > cap:
            current = cap
        result.append(current)
        # Next iteration: current * 2, but cap it
        current = min(cap, current * 2)
    
    return result
```