```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.0
        else:
            # Check if base * 2**i exceeds cap
            # We can compare using integer arithmetic if base is an integer,
            # but base can be a float. To avoid overflow, we check if 2**i is
            # so large that base * 2**i > cap.
            # Since cap is non-negative, if base > 0 and 2**i > cap / base,
            # then min(cap, base * 2**i) = cap.
            # But cap / base might be problematic if base is very small.
            # Alternative: compute step by step or use logarithms?
            # Simpler: if base * 2**i would overflow, it's definitely > cap (since cap is finite).
            # We can check if 2**i > cap / base when base > 0.
            # However, cap / base could be inf if base is very small, but that's fine.
            # Actually, the issue is that 2**i becomes a huge int, and multiplying by float base
            # causes OverflowError when converting int to float.
            # Solution: if base is 0, delay = 0.
            # If base > 0, we can check if 2**i > cap / base. If so, delay = cap.
            # But cap / base might not be exact. Better: use math.log2?
            # Or: since we only need min(cap, base * 2**i), and cap is finite,
            # once base * 2**i >= cap, all subsequent values are cap.
            # We can detect when base * 2**i >= cap without computing the huge number.
            # For base > 0: if 2**i >= cap / base, then delay = cap.
            # But cap / base could be a float. Let's use: if base > 0 and i is large enough
            # that base * 2**i > cap, we can set delay = cap.
            # To avoid overflow, we can check: if base > 0, compute threshold = cap / base.
            # If 2**i > threshold, delay = cap. But 2**i as int vs float threshold...
            # Actually, simpler approach: if base == 0, delay = 0.
            # Otherwise, for each i, if base * 2**i would overflow, it's > cap, so delay = cap.
            # We can check if 2**i > cap / base when base > 0.
            # But cap / base might be inf. If cap is 0, delay is 0 for all.
            # Let's handle: if base == 0 or cap == 0, delay = 0.
            # If base > 0 and cap > 0:
            #   if 2**i > cap / base, delay = cap.
            #   else, delay = base * 2**i.
            # But cap / base is a float, and 2**i is an int. Comparing int to float is fine
            # as long as the int isn't too large to convert to float. But that's the problem!
            # So we need to avoid converting 2**i to float.
            # Alternative: use logarithms. log2(2**i) = i. So if i > log2(cap / base), delay = cap.
            # But log2(cap / base) might be problematic if cap / base is very small or large.
            # Let's use: if base > 0 and cap > 0, compute log_threshold = math.log2(cap / base).
            # If i > log_threshold, delay = cap. Else, delay = base * 2**i.
            # But we can't import math? The problem says no third-party libraries, but math is standard.
            # Actually, the problem