Fra*_*sco 12 c++ templates crtp
我试图了解标准的简单CRTP模式是否有效.
下面的代码编译并按预期工作(在clang上).
但是我对相关标准章节/段落的理解是,虚函数CRTP <Derived,Base> :: DoSomething()的实例化应该在代码的点(B)处,其中Derived的完整声明不是可用.因此内部typedef类型也不应该可用.
任何人都可以指出验证此代码的相关标准章节吗?
换句话说,在这种情况下,虚拟函数被实例化ATFER点C?非常感谢您的任何见解.
弗朗切斯科
//-------------------------
// START CODE
#include <iostream>
struct Type1 {};
struct Type2 {};
struct Base
{
virtual ~Base() {}
virtual void DoSomething() = 0;
};
template< typename T, typename U >
struct CRTP : U
{
virtual void DoSomething() { DoSomething( typename T::Type() ); }
void DoSomething( Type1 ) { std::cout << "1\n"; }
void DoSomething( Type2 ) { std::cout << "2\n"; }
};
// (A) point of inst. of CRTP< Derived, Base > ( 14.7.1.4 ) ??
// (B) point of inst. of CRTP< Derived, Base >::DoSomething() (14.6.4.1.4 ) ??
struct Derived : CRTP< Derived, Base >
{
typedef Type2 Type;
};
// (C)
int main()
{
Base * ptr = new Derived;
ptr->DoSomething();
delete ptr;
}
// END CODE
//-------------------------
Run Code Online (Sandbox Code Playgroud)
相关(?)标准段落:
14.6.4.1 4如果隐式实例化虚函数,则其实例化点紧跟其封闭类模板特化的实例化之后.
14.7.1 4如果在需要完全定义的对象类型的上下文中使用类类型,或者类类型的完整性可能影响程序的语义,则会隐式实例化类模板特化.
14.7.1 9实现不得隐式实例化不需要实例化的类模板的函数模板,成员模板,非虚拟成员函数,成员类或静态数据成员.如果虚拟成员函数不会被实例化,则实现是否隐式实例化类模板的虚拟成员函数是未指定的.
这似乎是编译器延迟实例化CRTP<Derived, Base>::DoSomething()
直到翻译单元结束的结果,因为它允许这样做(参见CWG issue 993).
CRTP<Derived, Base>
肯定是在Derived
(§14.6.4.1[temp.point]/p4 的定义之前实例化,所有引用都是N3936):
对于类模板特化,类成员模板特化或类模板的类成员的特化,如果特化是隐式实例化的,因为它是从另一个模板特化中引用的,如果引用特化的上下文取决于在模板参数上,如果在封闭模板的实例化之前未实例化特化,则实例化的点紧接在封闭模板的实例化之前.否则,这种特化的实例化点紧接在引用特化的命名空间范围声明或定义之前.
是否CRTP<Derived, Base>::DoSomething()
需要实例化取决于需要成员定义存在的上下文中引用的短语的含义(§14.7.1[temp.inst]/p2).所有非纯虚函数都是使用过的(§3.2[basic.def.odr]/p2),并且"每个程序应该只包含每个非内联函数或该程序中使用的变量的一个定义" (§3.2[basic.def.odr]/p4); 是否计为"在需要成员定义存在的上下文中引用"尚不清楚.
(但是,即使不需要实例化,编译器仍然可以根据§14.7.1[temp.inst]/p11自由实例化它 - "未指定实现是否隐式实例化虚拟成员函数如果虚拟成员函数不会被实例化,则为类模板.".)
如果CRTP<Derived, Base>::DoSomething()
确实是实例化的,则情况由§14.6.4.1[temp.point]/p5和p8(强调我的)涵盖:
5如果隐式实例化虚函数,则其实例化点紧跟其封闭类模板特化的实例化之后.
8 甲专业化为函数模板,成员函数模板,或成员函数的或静态数据成员类模板可以具有实例化的多个点翻译单元内,并且除了如上所述,对于任何实例化的点在翻译单元内具有实例化点的这种专门化,翻译单元的结尾也被认为是实例化的点.类模板的专门化在翻译单元中最多只有一个实例化点.任何模板的特化可以在多个翻译单元中具有实例化点.如果两个不同的实例化点根据一个定义规则(3.2)给出模板特化不同的含义,则程序是不正确的,不需要诊断.
也就是说,它有两个实例化CRTP< Derived, Base >
点,一个在实例化之后,一个在翻译单元的末尾.在这种情况下,在实例化的两个点上,名称查找typename T::Type
会产生不同的结果,因此程序格式错误,无需诊断.
归档时间: |
|
查看次数: |
1079 次 |
最近记录: |