```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, i.e., 2**i > cap / base
        # To avoid computing huge 2**i, we can check if i is large enough that 2**i * base > cap
        # Since cap and base are non-negative, if cap == 0, then min(cap, ...) = 0
        if cap == 0:
            result.append(0.0)
            continue
        
        # We need min(cap, base * 2**i)
        # If base * 2**i >= cap, then result is cap
        # Otherwise, result is base * 2**i
        
        # To avoid overflow, check if 2**i * base > cap
        # This is equivalent to 2**i > cap / base
        # We can compute this safely by checking if i is large enough
        
        # If base * 2**i would overflow, we know it's > cap (since cap is finite), so result = cap
        # But we need to be careful: if base * 2**i <= cap, we compute it normally
        
        # Check if 2**i * base > cap
        # If i is large, 2**i can be huge. We can check if i > some threshold.
        # Alternatively, we can compute step by step and break early.
        
        # Let's compute iteratively to avoid huge numbers
        # Start with current = base
        # For each i, current = base * 2**i
        # But we can track current and multiply by 2 each time
        
        # Actually, let's use a different approach:
        # For each i, compute base * 2**i
        # If base * 2**i > cap, result = cap
        # Else, result = base * 2**i
        
        # To avoid overflow, we can check if 2**i > cap / base
        # Since cap and base are floats, cap / base is a float
        # If i is large enough that 2**i > cap / base, then result = cap
        
        # We can compute 2**i as a float, but if i is very large, 2**i as float can overflow
        # So we need to check if i is large enough that 2**i * base > cap
        
        # Let's compute threshold: if base * 2**i > cap, then 2**i > cap / base
        # Take log2: i > log2(cap / base)
        # But we don't want to use math.log2 (no imports allowed)
        
        # Alternative: compute iteratively
        current = base
        for i in range(attempts):
            if current > cap:
                result.append(cap)
            else:
                result.append(current)
            current *= 2
            # If current becomes inf or too large, we can break and fill with cap
            if current > cap:
                # All remaining will be cap
                for j in range(i + 1, attempts):
                    result.append(cap)
                break
        else:
            # If we didn't break, all values were computed
            pass
        
        # Wait, the above logic has an issue: we need to handle the case where current starts at base
        # Let me restructure:
        
        # Actually, let's just compute iteratively and handle overflow
        result = []
        current = base
        for i in range(attempts):
            if current > cap:
                result.append(cap)
            else:
                result.append(current)
            current *= 2
            # Check if current is inf or too large
            if current == float('inf') or current > cap:
                # Fill remaining with cap
                for j in range(i +