boost::capy::DynamicBufferParam

Concept for valid DynamicBuffer parameter passing to coroutines.

Synopsis

template<class B>
concept DynamicBufferParam = DynamicBuffer<std::remove_cvref_t<B>> &&
    (std::is_lvalue_reference_v<B> ||
     requires { typename std::remove_cvref_t<B>::is_dynamic_buffer_adapter; });

Description

This concept constrains how a DynamicBuffer type can be passed to coroutine‐based I/O functions. It allows:

Lvalues of any DynamicBuffer (caller manages lifetime) ‐ Rvalues only for types with is_dynamic_buffer_adapter tag

The distinction exists because some buffer types (like flat_dynamic_buffer) store bookkeeping internally that would be lost if passed by rvalue, while adapters (like string_buffers) update external storage directly.

Conforming Signatures

For coroutine functions, use a forwarding reference:

io_task<std::size_t>
read( ReadSource auto& source, DynamicBufferParam auto&& buffers );

The forwarding reference is essential because the concept inspects the value category to enforce the lvalue/rvalue rules. Using the wrong reference type causes incorrect behavior:

// WRONG: lvalue ref rejects valid rvalue adapters
void bad1( DynamicBufferParam auto& buffers );
bad1( fb );                    // OK
bad1( string_buffers( s ) );   // compile error, but should work

// WRONG: const ref deduces non-reference, rejects non-adapters
void bad2( DynamicBufferParam auto const& buffers );
bad2( fb );                    // compile error, but should work
bad2( string_buffers( s ) );   // OK (adapter only)

// CORRECT: forwarding ref enables proper checking
void good( DynamicBufferParam auto&& buffers );
good( fb );                    // OK: lvalue
good( string_buffers( s ) );   // OK: adapter rvalue
good( flat_dynamic_buffer( storage ) );  // compile error: non-adapter rvalue

Adapter Types

Types safe to pass as rvalues define a nested tag:

class string_dynamic_buffer {
public:
    using is_dynamic_buffer_adapter = void;
    // ...
};

Example

// OK: lvalue reference
flat_dynamic_buffer fb( storage );
co_await read( stream, fb );

// OK: adapter as rvalue, string retains data
std::string s;
co_await read( stream, string_dynamic_buffer( &s ) );

// ERROR: non-adapter rvalue
co_await read( stream, flat_dynamic_buffer( storage ) );  // compile error

See Also

DynamicBuffer

Created with MrDocs