#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.
friend class buffer_stream<shared_array_buffer>;
This makes the is_buffer concept check if shared_array_buffer is valid, but shared_array_buffer is not complete that the point of the friend declaration, so compilation fails.
A workaround could be to delay the validation using a static_assert instead:
template <typename Buffer>
class buffer_stream {
static_assert(is_buffer<Buffer>);
};
Another option is to let buffer_stream inherit from the buffer type. You can then create protected accessors that it can use and don't need to make it a friend:
class shared_array_buffer {
private:
struct meta {
char* ptr{};
size_t capacity{};
std::mutex mutex{};
std::shared_mutex rwlock{};
int reference_count{};
};
meta* meta_{};
public:
char* pointer() { return meta_->ptr; }
size_t capacity() { return meta_->capacity; }
std::shared_mutex& rwlock() { return meta_->rwlock; }
};
template <typename Buffer>
requires is_buffer<Buffer>
class buffer_stream : public Buffer {
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With