通过 typedef 模板<类型名 T、T> 强制模板实例化 - 为什么有效?
Force template instantiation via typedef template<typename T, T> - why it works?
我正在学习强制模板实例化。
它有效,但我仍然很好奇:-
#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
已正确实例化。
观察
- 如果我删除行
#2#
,它将打印 0。 (InitCRTP<WantInit>::init
未实例化(。 如果我将
#2#
从int&
更改为int
,我会得到:-错误:"InitCRTP::init"的值在常量中不可用 表达
如果我将
#1#
更改为template <T>struct NonTypeParameter { };
并将#2#
更改为public: using dummy=NonTypeParameter<init>;
,我将得到:-错误:"T"尚未声明
问题
为什么行
#2#
足以强制实例化?
在我看来,它只是模板类中的一个typedef,任何人都无法访问。为什么我需要
int&
作为另一个模板参数才能使其可编译?
一个可能更正确的问题:该技术的名称是什么?
原文帖子 : 使用 CRTP 强制显式模板实例化
为什么行 #2# 足以强制实例化?
若要提供第二个参数,编译器必须绑定引用。这意味着它 ODR 使用静态变量,因此该变量必须存在并具有唯一的标识。因此,它的定义是实例化的。
当你使用纯int
时,第二个参数只能接受整数常量表达式。非常量静态在常量表达式中不可用。
为什么我需要
int&
作为另一个模板参数才能使其可编译?
您需要声明第二个参数的引用类型,以具有编译器可以检查的类型。好吧,在 C++17 之前,无论如何您都需要这样做。如今,我们可以改用占位符类型。
template <auto&>struct NonTypeParameter { };//#1#
using dummy=NonTypeParameter<init>;//#2#
这将 ODR 使用静态传递的,而不必显式指定引用类型。
相关文章:
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 为什么C++无法识别我的对象实例化?
- 为什么我们不在下面给出的代码中使用指针来实例化C++的实体对象?
- 为什么显式模板实例化不会破坏 ODR?
- 为什么我不能引用指向实例化对象的函数的指针?
- 使用用户定义的类型 UDT 实例化 std::atomic<>。如果 UDT 具有虚函数,则 l 墨水将失败。为什么?
- 为什么在使用指针时不采用类成员的默认值,而不是直接实例化对象时?
- 为什么我不能更改实例化对象内部的向量?
- 为什么显式模板实例化不起作用
- 为什么不能在实例化对基类的引用的同时实例化指向派生类的指针?
- SFINAE 和模板函数实例化:为什么在启用了 SFINAE 类型的函数参数中使用模板参数时无法推断模板参数?
- 通过 typedef 模板<类型名 T、T> 强制模板实例化 - 为什么有效?
- 为什么在共享库中仅导出其中一些C++模板实例化?
- 为什么找不到使用命名空间中定义的类型实例化的 std::weak_ptr 的重载运算符==?
- 为什么显式模板实例化不起作用?
- 使用大括号实例化 - 它是什么,为什么在这里使用它?
- 为什么C++可以使用派生结构来实例化其父模板结构,而父模板可以调用子结构的函数?
- 为什么当我在构造函数中创建线程时,实例化对象和对象的指针的行为不同
- c++模板实例化——为什么我必须总是显式的,不像STL