Search code examples
c++templatesexplicit-instantiation

Are standard library non-type template classes explicitly instantiated?


When we have a templated class (or function) that has a non-type template parameter, how are the versions generated by the compiler? Surely it doesn't create a version for every possible value of N

Suppose something like std::array<T,N> ?

I am trying to write my own templated function with a size_t template parameter, and I am trying to figure out whether/how I need to explicitly instantiate versions I will use

(I have split the program across different translation units)

I have a templated function which is something like

template <size_t N>
std::bitset<N> f(std::bitset<N> A){}

I put the declaration into a header file and definition into a .cpp file. It doesn't generate the correct version. So I tried to explicitly instantiate it like

template std::bitset<10> f<10>(std::bitset<10> A);

but I get the error that "error: explicit instantiation of .... but no definition available"


Solution

  • Neither the standard library nor you need to explicitly instantiate any template specialization, whether it has non-type template parameters or not.

    Any specialization of the template which is used by the user in a way that requires a definition for the specialization to exist will cause it to automatically be implicitly instantiated if a definition for the entity which is instantiated is available. The condition should normally always be fulfilled since it is standard practice to place definitions of templated entities into the header file along with their initial declaration, so that they are accessible in all translation units using them.

    So std::array<T,N> will be implicitly instantiated for all pairs of types T and values N which are actually used by the translation unit.

    The only situation where explicit instantiation is required is if you intent to separate the definitions of template members into a single translation unit instead of the header file where they would be available for all translation units to implicitly instantiate. But you can only do that in the first place if you know all possible values for the template parameters, and you would then need to explicitly instantiate all of them, which for most non-type template parameters is not feasible.

    Aside from that explicit instantiation may be used as an optimization of compilation time by avoiding implicitly instantiating template specializations in every translation unit where they are used. That makes sense only for specializations which you know will be often used. For example some standard library implementations apply it to std::string, which is the specialization std::basic_string<char>. It doesn't really make sense to apply it to e.g. std::array.