我想我应该尝试找出我的特定编译器(Linux 上的 g++ 4.8.1)的模板参数数量是否有限制。我使用了以下测试用例:
template <int I>
struct this_is_a_ridiculously_long_struct_name_youd_never_use_in_real_life {};
template <int Depth, typename... T>
struct A
{
using e = this_is_a_ridiculously_long_struct_name_youd_never_use_in_real_life<Depth>;
A() {};
A<Depth - 1, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, T...> a;
};
template <typename... T>
struct A<0, T...>
{
};
int main()
{
A<899> a;
}
g++ 中的模板递归深度限制默认为 900,因此您看到的是 899 参数。这个长得可笑的结构名称用于查看我是否可以生成任何对于链接器来说太大而无法处理的符号——稍后会详细介绍。
如果您看不到测试用例中发生了什么,基本上每个实例A
创建一个成员变量,添加 20 个额外的模板参数。部分特化用于停止递归。到最后,A<0, ...>
有大约 18000 个模板参数。
我发现 g++ 处理得很好。我考虑了很长时间,并且使用了相当多的内存,但我无法仅仅通过增加模板参数的数量来让它失败。一旦模板递归深度设置得足够(即 900),Clang 3.1 也可以毫无问题地处理这个问题。
此外,虽然损坏的符号名称确实变得很大,但我无法破坏其中任何一个nm
or ld
使用它们。 (值得注意的是,Linux/Itanium 重整方案使用替换,以便相同类型的重复模板参数不会重复整个类型名称,而是被标记S0
, S1
等等)快速谷歌似乎没有发现 ELF 符号长度的任何限制,但也许其他人知道是否存在这样的限制。
总之,至少对于 Linux 上的 g++ 和 clang,模板参数的数量似乎没有任何实际限制.
至于你问题的第二部分,关于代码膨胀,很难说,特别是一旦涉及编译器优化。使用可变参数模板进行递归很容易,但编译器也很容易摆脱中间类型。我只能建议尝试一下看看。