现在,我对模板很熟悉,对 SFINAE 之类的东西也有些熟悉,而且我一直想知道当模板被编译器实例化时会发生什么。
当你在 TMP 中做一些事情时,比如 SFINAE,甚至是 TMP 中的简单斐波那契数列,似乎编译器所做的比我在模板实例化下理解的要多。似乎编译器正在执行模板代码。
我的问题是,模板实例化到底是什么,编译器实际执行代码的线在哪里?
编译器创建一个你的模板类型,是我对模板实例化的理解。但在 TMP 中,它的作用似乎远不止于此,这让我感到困惑。
现在,我对模板很熟悉,对 SFINAE 之类的东西也有些熟悉,而且我一直想知道当模板被编译器实例化时会发生什么。
当你在 TMP 中做一些事情时,比如 SFINAE,甚至是 TMP 中的简单斐波那契数列,似乎编译器所做的比我在模板实例化下理解的要多。似乎编译器正在执行模板代码。
我的问题是,模板实例化到底是什么,编译器实际执行代码的线在哪里?
编译器创建一个你的模板类型,是我对模板实例化的理解。但在 TMP 中,它的作用似乎远不止于此,这让我感到困惑。
最好把它想象成一堆函数,这就是它的本质。考虑一个 class Type
,它在这里表示编译器对类型的内部表示。
template<typename T> class X {
T t;
};
在运行时 C++ 中,您可以将其表示为
Type* X(Type *t) {
static std::unordered_map<Type*, Type*> cache;
if (cache.find(t) != cache.end())
return cache[t];
Type* ret = new Type;
ret->DataMembers.insert("t", t);
return cache[t] = ret;
}
当然,专业化等需要一些额外的费用。但是,使用这个模型很容易做两件事。
A) 实例化模板相当于函数调用,它恰好发生在编译时,就像constexpr
. 当然,一个聪明的编译器可能会做一些其他的优化,但在一般情况下。
B) 它如何扩展到模板提供的任何其他功能。
因为实例化模板是图灵完备的,所以您无法以其他任何方式真正处理它。编译器似乎正在执行它们的原因是因为它是. 它们只不过是语法错误的有限 EDSL 中的函数。