#include <mutex>
#include <shared_mutex>
template<typename T>
concept is_buffer = requires (T t) {
{ t.pointer() } -> std::same_as<char*>;
{ t.capacity() } -> std::same_as<size_t>;
{ t.rwlock() } -> std::same_as<std::shared_mutex&>;
};
template<typename Buffer>
requires is_buffer<Buffer>
class buffer_stream {
};
class shared_array_buffer {
private:
struct meta {
char* ptr {};
size_t capacity {};
std::mutex mutex {};
std::shared_mutex rwlock{};
int reference_count {};
};
meta* meta_ {};
/* Error occured here */
friend class buffer_stream<shared_array_buffer>;
public:
char* pointer() {
return meta_->ptr;
}
size_t capacity() {
return meta_->capacity;
}
std::shared_mutex& rwlock() {
return meta_->rwlock;
}
};
int main() {
shared_array_buffer buffer;
buffer_stream<shared_array_buffer> stream;
}
In this code, I use the class buffer_stream as the friend class of shared_array_buffer and unique_array_buffer, they are all template class with concept.
The compiler says template constraint failure for ‘template<class Buffer> requires is_buffer<Buffer> class buffer_stream’ because ‘t’ has incomplete type(in class shared_array_buffer).
I wonder why the shared_array_buffer is an incomplete type.All the types of the member is fully defined.
This makes the
is_bufferconceptcheck ifshared_array_bufferis valid, butshared_array_bufferis not complete that the point of thefrienddeclaration, so compilation fails.A workaround could be to delay the validation using a
static_assertinstead:Another option is to let
buffer_streaminherit from the buffer type. You can then createprotectedaccessors that it can use and don't need to make it afriend: