I have a fair understanding of how type-template parameters get compiled. But do non-type templates get compiled the same way?
For instance, with a type-template like this:
template<typename T>
class TemplatedClass {
..do something with T..
};
TemplatedClass<int> IntClass;
TemplatedClass<char> CharClass;
The above would get compiled to separate class definitions for int and char:
class TemplatedClass<int> {
..do something with int..
};
class TemplatedClass<char> {
..do something with char..
};
When templating non-type parameters, does the compiler do it the same way? For instance:
template<int N>
class NumericClass {
int array[N];
..do something else with N..
};
NumericClass<3> Class3;
NumericClass<5> Class5;
Would this generate separate class definitions for each of the numeric values as below?
class NumericClass3 {
int array[3];
..do something else with 3..
};
class NumericClass5 {
int array[5];
..do something else with 5..
};
If so, couldn't that lead to a ton of bloated compiled code if there are a significantly large number of numeric possibilities for the template parameter? I could have a static array class defined with a numeric template in my core API. Then every time I declared an instance with a unique length value, it would have to compile a new class definition for it. This could lead a ridiculously large number of compiled definitions, assuming my code is open-ended.
As far as I know, this is still encouraged practice. Does the compiler have some other way of dealing with non-type templates then? Or are the overheads from having it compiled this way not all that significant?
Each template instantiation is conceptually a different entity. The compiler can create different code for each instantiation. It doesn't matter whether the template arguments are type or non-type arguments. The compiler may be able to share code between different instantiations and give different symbols to the same object code but there is certainly no mandate to do so (there is still some storage needed for the symbols at least until the code is linked).
As a result, it can be important to structure implementations in a way minimizing the code which is specific to template arguments. For example, it may be reasonable to factor code common to multiple instantiations into a base class (assuming the functionality has to be a member functions). For the remaining code it is reasonable to make it rather small so that it can be inlined and not create any overhead if it is smaller than code needed to call functions and return from them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With