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

标签 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 ,我会得到:-

    error: the value of 'InitCRTP::init' is not usable in a constant expression

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

    error: 'T' has not been declared

问题

  1. 为什么这条线 #2#足以强制实例化吗?
    在我看来,它只是模板类中的 typedef,任何人都无法访问。

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

原帖:Force explicit template instantiation with CRTP

最佳答案

Why the line #2# is enough to force instantiation?

为了提供第二个参数,编译器必须绑定(bind)一个引用。这意味着 ODR 使用静态变量,因此该变量必须存在并具有唯一标识。因此,它的定义已实例化。

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

Why do I need int& as another template parameter to make it compilable?

您需要声明第二个参数的引用类型,以便编译器可以检查该类型。好吧,在 C++17 之前你无论如何都需要这样做。现在我们可以使用占位符类型来代替。

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

这将 ODR 使用传入的静态,而无需显式指定引用类型。

关于c++ - 通过 typedef template<typename T, T> 强制模板实例化 - 为什么它有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57951553/

相关文章:

C++ : CRTP destructor?

c++ - "if constexpr(something false)"是否总是省略模板实例化

c++ - 是否有缺少固定宽度类型 (intXX_t) 的平台?

c++ - 使用 QString 替换方法用正则表达式更改文件名

c++ - 指针越过对象的末尾是什么意思?

c++ - 根据实例化点期望不同的类型

c++ - 是否有显式实例化深层模板类的技巧?

c++ - ICU ustdio.h 函数 : Undefined symbols on Mac OS when building with CMake

c++ - libclang 可以解析 CRTP 模式吗?

c++ - 'using'指令如何与模板成员函数一起工作