C++ 模板友元类不满足概念约束,因为它是不完整类型

问题描述 投票:0回答:2
#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;
}

在这段代码中,我使用类

buffer_stream
作为
shared_array_buffer
unique_array_buffer
的友元类,它们都是有概念的模板类。

编译器说

template constraint failure for ‘template<class Buffer>  requires  is_buffer<Buffer> class buffer_stream’
,因为
‘t’ has incomplete type
(在类shared_array_buffer中)。

我想知道为什么

shared_array_buffer
是一个不完整的类型。成员的所有类型都是完全定义的。

c++ templates friend incomplete-type concept
2个回答
3
投票
friend class buffer_stream<shared_array_buffer>;

这使得

is_buffer
concept
检查
shared_array_buffer
是否有效,但
shared_array_buffer
不完整于
friend
声明的点,因此编译失败。

解决方法可能是使用

static_assert
来延迟验证:

template <typename Buffer>
class buffer_stream {
    static_assert(is_buffer<Buffer>);
};

另一种选择是让

buffer_stream
继承缓冲区类型。然后,您可以让它具有
protected
访问器等,而不需要将其设为
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 {
};

1
投票

我想这与实例化模板的顺序以及评估

requires
子句的时间有关。删除 require 子句并将其替换为
static_cast
似乎是一种解决方法:

template<typename Buffer>
// requires is_buffer<Buffer>             <--- this fails
class buffer_stream {
    static_assert(is_buffer<Buffer>);  // <--- this succeeds
};

这对于所有主要编译器的行为都是相同的请参阅演示

© www.soinside.com 2019 - 2024. All rights reserved.