奇怪的是重复出现的模板模式实现

Is Curiously Recurring Template Pattern Implementation Specific?

本文关键字:模式 实现      更新时间:2023-10-16

所以我已经阅读了此信息:https://en.wikipedia.org/wiki/curoite_recurring_template_pattern

并了解奇怪的重复模板模式(CRTP)的工作方式。但这似乎取决于编译器的实现,特别是编译器:

  1. 定义每个模板类所需的空间
  2. 然后编译孩子班的方法
  3. 然后编译父母类的方法

尽管我可以看到该订单允许编译,但我觉得这是一种利用编译器构造,而不是标准所需的编译器通行证订单。但是我觉得同样合法的编译器通行证将是:

  1. 定义父类所需的空间
  2. 编译父类方法
  3. 定义子类所需的空间
  4. 编译子类方法

如果编译器使用这些通过时,CRTP试图评估儿童类型时将在步骤2上失败。

因此,我刚刚编造了这些编译器,但是是否有标准要求在编译器上限制它,以使其遵守1 st 的3次通过?或CRTP存在于灰色区域中,知道当前如何实施编译器?


我看到的那样,允许标准需要一个1 st 通过以建立对象大小,然后是2 nd 通过来编译方法。但是,这个2 nd 通过,必须愿意在父对象之前构建子对象方法,这似乎是向后的。

CRTP从未被定义或有条件地支持,IIRC在发明时是一个惊喜,此后一直被接受。

来自[class]

a class-name 被插入在看到 class-name 之后立即声明的范围中。 class-name 也插入了类本身的范围。这被称为注射级 - 名称

其中 class-name 是声明的类的名称。因此

但是,允许模板使用不完整的类型作为类型arguments,从[temp]

模板类型参数可能是不完整的类型。

注意模板即使不是类型的参数也不是完成。

template<typename>
struct S {};
struct U     // U is visible after this line
    : S<U>   // S<U> is a complete type
{
    S<U> s;  // well-formed
};           // U is complete after this line

实例化模板可以完成的原因是,模板类型参数本身可能不完整,从而避免了循环逻辑

template<typename T>
struct A
{
    T t;  // ill-formed, incomplete type T in instantiation of A<B> from below
};
struct B : A<B>  // implicit instantiation of the specialization A<B>
{
};

我们得出结论模式是有效的。编译器如何设法编译它是无关紧要的,如果它是标准的一致性,它将编译该代码。

这是明确的。正如评论中指出的,即使标准也利用了功能。

思考的方法是,一旦您编写class Child,编译器就会考虑有效的类型的正向声明。因此,只要父类模板定义不取决于Child的完整类型,它将成功编译的父。[我相信父级模板类的大小不能取决于Child的定义,但我无法证明自己]请注意,父模板 method body 可以自由依靠完整的类型儿童是因为它们将是依赖类型,因此当Child的完整定义可用时,它们的实例化延迟到模板汇编的第二阶段。

no。CRTP不是特定于实施的。必须由任何标准的编译器支持。

从标准的话中证明这一点是一项艰巨的任务。如果有人带有参考文献的答案,我将删除此答案(并在此处发表评论以提醒我这样做)。


正如Passerby所说:

严格来说,它之所以起作用,是因为注入的类名称 base子句之前存在

基本子句是结肠之后的一切:

class Derived : CRTP<Derived>

正如FrançoisAndrieux和unterscore_d指出的那样,我们可以间接证明标准需要CRTP工作,因为它定义了使用CRTP的std::enable_shared_from_this。(但是,它在C 89中得到了很好的定义,并且直到C 11才添加enable_shared_from_this)。