c++ - 受限 CRTP 过早拒绝

标签 c++ templates c++-concepts incomplete-type

我正在尝试实现一个从基模板继承的派生类,并将派生类作为其模板参数(希望下面的示例能够澄清问题):

template <class T>
struct S
{
    T f() {return T();}
};

struct D : public S<D>
{
};

它也可以在 gcc、clang 和 msvc 上编译并运行良好。现在,我想“确保”模板参数继承自基类:

#include <concepts>

template <class T>
concept C
= requires ( T t )
{
    { t.f() };
};

template <C T>
struct S
{
    T f() {return T();}
};

struct D : public S<D>
{
};

但是,这会被每个编译器拒绝,而 clang 提供了最深入的见解:

error: constraints not satisfied for class template 'S' [with T = D]
struct D : public S<D>
                  ^~~~
note: because 'D' does not satisfy 'C'
template <C T>
          ^
note: because 't.f()' would be invalid: member access into incomplete type 'D'
    { t.f() };

我了解编译器的来源:当必须检查约束时,D 尚未完全定义,因此它会失败而不是必要的信息。也就是说,我有点失望的是,在评估尚未检查的约束之前,没有尝试完成派生类的定义。

这种行为是故意的吗?还有另一种方法来检查继承是否实际有效?

顺便说一下,gcc 给出了一个相当无用的 error message在这种情况下。

最佳答案

您可以在基类的默认构造函数中检查要求

#include <type_traits>

template<class Derived>
class Base
{
public:
    Base()
    {
        static_assert(std::is_base_of_v<Base<Derived>, Derived>);
    }
};

class Derived : public Base<Derived>
{ };

还必须在任何其他用户定义的基类非复制和非移动构造函数中检查这一点。这是有效的,因为在实例化构造函数时完全定义了 Derived

关于c++ - 受限 CRTP 过早拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68401401/

相关文章:

c++ - std::string assign、clear 和 operator[] 的奇怪行为

c++ - 如何使用模板类 C++

symfony - 如何从父包扩展 Twig 模板?

c++ - 使用 SFINAE、约束或概念来限制特化?

c++ - c++ 概念与 Haskell 类型类有何不同?

c++ - 为什么线程会减慢程序的执行速度?

c++ - 以编程方式清除 Linux 中已安装 (SSD) 磁盘上的缓存

c++ - 嵌套的依赖名称不在模板中评估概念

php - 为什么我在 C++ 和 PHP SHA256 哈希之间得到不同的结果?

c++ - 创建模板类的 std::vector ?