编译器是否C++具有相同模板参数集的每个模板类实例生成代码?

Does C++ compiler generate code for every template class instance with the same set of template parameters?

本文关键字:实例 代码 参数 C++ 是否 编译器      更新时间:2023-10-16

以免考虑众所周知的编译时递归斐波那契计算。在这种特殊情况下,fibonacci<1>(或fibonacci<20>无关紧要(被实例化了多少次?是一次吗?如果是,编译器为我们执行动态编程算法:)

template<int n>
struct fibonacci
{
static const uint64_t value = fibonacci<n - 1>::value + fibonacci<n - 2>::value;
};
template<>
struct fibonacci<0>
{
static const  uint64_t value = 0;
};
template<>
struct fibonacci<1>
{
static const uint64_t value = 1;
};
int main()
{
std::cout << fibonacci<80>::value;
}

让我们考虑另一个例子。

int main()
{
std::vector<int> v1;
std::vector<int> v2;
}

编译器C++是否为vector<int>的两个实例生成单独的代码代码? 如果类似的vector<int>实例位于不同的翻译单元中,该怎么办?

C++标准并不强制要求其中一个。只要完成的程序按照指定的方式运行,编译器就可以做任何事情,参见所谓的"as-if"规则(§1.9-1(。一个好的编译器不会生成不必要的代码,所以我希望它能将斐波那契示例优化为常量,将向量示例优化为向量函数的一个实现。

你在这里依赖于一种叫做"隐式实例化"的东西。显式模板实例化将是

template class fibonacci<0>;
template class fibonacci<1>;
template class fibonacci<2>;
// etc

现在,显式模板实例化的可能性允许您关闭隐式实例化:

extern template class fibonacci<0>;
extern template class fibonacci<1>;
extern template class fibonacci<2>;
// etc

为什么这很重要?这意味着编译器已经有一个相当精细的机制来处理模板实例化。要使隐式实例化正常工作,编译器必须能够检查实例化状态,因此它不会隐式实例化已显式实例化的模板。

因此,有一个"实例化状态是什么?"检查。这可能会返回"已经隐式实例化"。在这种情况下重新实例化模板将是一种悲观!

在这种特殊情况下,斐波那契<1>(或斐波那契<20>无关紧要(被实例化了多少次?

零个对象,只有一个静态(常量!(值。

std::vector<int> v1;
std::vector<int> v2;

实例化为两个对象。