通过typedef template <typename T,T>强制模板实例化-为什么有效?

时间:2019-09-16 06:39:38

标签: c++ crtp template-instantiation

我正在学习强制模板实例化。
它有效,但我仍然很好奇:-

#include <iostream>
#include <string>
template <typename T, T>struct NonTypeParameter { };//#1#
int lala=0;
template <typename T> class InitCRTP{
    public: static int init;
    public: using dummy=NonTypeParameter<int&, init>;   //#2#
};
template <typename T> int InitCRTP<T>::init = lala++;
class WantInit : public InitCRTP<WantInit>{
};
int main(){
    std::cout << lala << std::endl;
}

它打印1,因为InitCRTP<WantInit>::init已正确实例化。

观察

  1. 如果我删除行#2#,它将打印0。(InitCRTP<WantInit>::init未实例化)。
  2. 如果将#2#int&更改为int,我会得到:-

      

    错误:“ InitCRTP :: init”的值不能在常量中使用   表达

  3. 如果将#1#更改为template <T>struct NonTypeParameter { };,将#2#更改为public: using dummy=NonTypeParameter<init>;,我将得到:-

      

    错误:尚未声明'T'

问题

  1. 为什么#2#行足以强制实例化?
    我认为,这只是在模板类中的typedef ,任何人都不能访问。

  2. 为什么需要int&作为另一个模板参数才能使其可编译?
    一个可能更正确的问题:该技术的名称是什么?

原始帖子:Force explicit template instantiation with CRTP

1 个答案:

答案 0 :(得分:4)

  

为什么#2#行足以强制实例化?

要提供第二个参数,编译器必须绑定一个引用。表示它的ODR使用静态变量,因此该变量必须存在并具有唯一标识。嗯,它的定义实例化了。

使用纯int时,第二个参数只能接受整数常量表达式。非常量静态在常量表达式中不可用。

  

为什么我需要int&作为另一个模板参数才能使其可编译?

您需要声明第二个参数的引用类型,以使编译器可以检查该类型。好吧,在C ++ 17之前,您仍然需要。如今,我们可以改用占位符类型。

template <auto&>struct NonTypeParameter { };//#1#
using dummy=NonTypeParameter<init>;//#2#

这将ODR使用静态传递的内容,而不必显式指定引用类型。