给定以下 CRTP 示例:
template <typename T>
int foo(T* const)
{
return 0;
}
template <typename Derived>
struct Base
{
Base() : bar(foo(static_cast<Derived*>(this)) {};
int bar;
};
struct Derived1 : Base<Derived1> {};
this
到这里的转换Derived*
有效吗?我似乎记得可能不是,但现在找不到具体的证据。
this
此阶段的“自然”类型是Base* const
,并且在某些情况下,即使this
在初始化期间静态转换指针也是不行的,例如在基础构造完成之前向上转换(12.7/3)。
@DeadMG 说:
在初始化列表中获取这个的标准中有一个明确的例外。它用于将指向您自己的指针传递给子对象。
12.6.2/12 确实说:
[ 注意:因为 mem-initializer 是在构造函数的范围内计算的,所以 this 指针可以在 mem-initializer 的表达式列表中使用来引用正在初始化的对象。——尾注]
...虽然这不足以说转换Derived*
为有效。
我的直觉是,在对象初始化的这个阶段,this
它并没有指向一个实例,因此,严格来说,Derived
即使只是有一个指向它的类型的指针也是 UB。Derived*
那是因为它既不是有效指针也不是空指针。
(这可能对这样的方法产生实际影响,尽管在那个答案和我上面的例子中,整个事情可以通过简单地编写static_cast<Derived*>(0)
来回避。)