非类型模板参数如何编译?

6

我对类型模板参数的编译方式有一定的了解。但是非类型模板也会以同样的方式进行编译吗?

例如,对于以下类型模板:

template<typename T>
class TemplatedClass {
    ..do something with T..
};
TemplatedClass<int> IntClass;
TemplatedClass<char> CharClass;

以上内容将被编译为int和char的分别类定义:
class TemplatedClass<int> {
    ..do something with int..
};
class TemplatedClass<char> {
    ..do something with char..
};

当模板化非类型参数时,编译器是否以相同的方式进行处理?例如:

template<int N>
class NumericClass {
    int array[N];
    ..do something else with N..
};
NumericClass<3> Class3;
NumericClass<5> Class5;

这会为数值中的每个类型生成单独的类定义,就像下面这样吗?
class NumericClass3 {
    int array[3];
    ..do something else with 3..
};
class NumericClass5 {
    int array[5];
    ..do something else with 5..
};

如果是这样,如果模板参数存在大量数字可能性,那么是否会导致大量膨胀的编译代码?我可以在我的核心API中定义一个带有数字模板的静态数组类。然后,每次我使用唯一长度值声明实例时,都必须为其编译一个新的类定义。假设我的代码是开放式的,这可能会导致大量编译定义。

据我所知,这仍然是鼓励的做法。编译器是否有其他处理非类型模板的方法?或者说,以这种方式进行编译的开销并不是很大吗?

6
每个不同的数字都将实例化不同的类。 - πάντα ῥεῖ
如果你真的需要它(即使经过可能的优化),那么内存就不能来自空间。 - edmz
Itanium C++ ABI 展示了模板参数如何被编码成(类模板,类模板的成员函数等)特化名称的一种方式。(请注意 表达式是如何被编码的。) - dyp
假设编译器没有其他处理非类型模板参数的方法,似乎最好始终坚持一些离散的数值集合作为数字模板参数。我可能总是使用Class<16>、Class<32>、Class<64>等,而不是尽可能使用连续范围的值,这样只有有限数量的定义被编译。 - Tahsin M
1个回答

3
每个模板实例在概念上都是一个不同的实体。编译器可以为每个实例创建不同的代码。无论模板参数是类型还是非类型参数,都没有关系。编译器“可能”能够在不同的实例之间共享代码并为相同的对象代码提供不同的符号,但肯定没有必要这样做(至少需要一些存储空间来存储符号,直到代码链接)。
因此,重要的是以最小化特定于模板参数的代码为目标组织实现结构。例如,将多个实例共有的代码因素化为基类可能是合理的(假设功能必须是成员函数)。对于其余的代码,使其尽可能小,以便可以内联,并且如果它比调用函数和从函数返回所需的代码小,则不会产生任何开销。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接