```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 exceeds 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, i.e., 2**i > cap / base
        # To avoid overflow, we can check if i is large enough that 2**i * base > cap
        # Since cap and base are non-negative, if base > 0:
        #   2**i * base > cap  <=>  2**i > cap / base
        # We can compute this safely by checking if i >= some threshold
        # Alternatively, compute step by step with early termination
        
        # Use logarithm-free approach: check if 2**i * base > cap
        # If base > 0, then 2**i > cap / base
        # We can check if i is large enough that 2**i > cap / base
        # But to avoid overflow, we can compute iteratively
        
        # Simpler: compute value = base * (2 ** i) but guard against overflow
        # If 2**i is too large, then base * 2**i > cap (since cap is finite)
        # So we can check: if i is large enough that 2**i * base > cap, use cap
        
        # Check if 2**i * base > cap
        # If base == 0, handled above
        # If base > 0:
        #   2**i * base > cap  <=>  2**i > cap / base
        # We can check if i >= log2(cap / base) + 1, but avoid float issues
        
        # Instead, compute iteratively:
        # Start with power = 1, multiply by 2 each step, check if power * base > cap
        
        # But we need to do this for each i, so let's compute power incrementally
        
        # Actually, let's just compute 2**i safely:
        # If i is large, 2**i might overflow when converted to float
        # But we only need min(cap, base * 2**i)
        # If base * 2**i > cap, we return cap
        # So we can check if 2**i > cap / base (when base > 0)
        
        if base > 0:
            # Check if 2**i * base > cap
            # This is equivalent to 2**i > cap / base
            # To avoid overflow, check if i is large enough
            # We can compute cap / base as a float, but cap and base might be large
            # Instead, check if 2**i > cap / base by comparing i to log2(cap/base)
            # But to avoid float issues, let's use integer comparison
            
            # If cap == 0, then min(cap, base * 2**i) = 0
            if cap == 0:
                result.append(0.0)
                continue
            
            # Check if 2**i * base > cap
            # If base > 0 and cap > 0:
            #   2**i > cap / base
            # We can check if i >= some value
            
            # Compute threshold: smallest i such that 2**i * base > cap
            # i > log2(cap / base)
            # But to avoid float, let's compute iteratively
            
            # Simpler approach: compute power = 2**i, but if power * base > cap, use cap
            # To avoid overflow, check if power * base > cap before computing full power
            
            # Let's compute power incrementally
            power = 1
            for j in range(i + 1):
                if power * base > cap:
                    result.append(cap)
                    break
                power *= 2
            else:
                result.append(base * power)
        else:
            # base == 0, already handled above
            result.append(0.0)
    
    return result
```