Search code examples
c++templatesinstantiationshort-circuiting

Short-circuiting while instantiating template?


Consider this code snippet,

template<bool b>
struct other
{
    static const bool value = !b;
};

template<bool b>
struct test
{
    static const bool value = b || other<b>::value;
};

int main()
{
      bool value = test<true>::value;   
}

Do compilers instantiate other<true> in situations such as the above, when instantiating seems completely unnecessary? Or just because I've written the syntax other<b>::value, compilers must instantiate it regardless of the fact that it contributes absolutely nothing to the calculation of the value of test<true>::value?

I would like to hear, a) what is required by the Standard, and b) what is actually implemented by the various compilers? Relevant sections from the Standard would be appreciated.


Solution

  • According to the C++ spec, section $14.7.1/4:

    "A class template specialization is implicitly instantiated if the class type is used in a context that requires a completely-defined object type or if the completeness of the class type affects the semantics of the program; in particular, if an expression whose type is a class template specialization is involved in overload resolution"

    In the case you illustrated with short-circuiting, the class would have to have a complete type, because you're looking inside of it to find the value static member. This precludes the compiler from short-circuiting the expression.

    As for what actually happens in practice, I'm not sure because I can't see how the compiler could get away with not doing the instantiation. For example, suppose that the instantiation of other<b> looked like this:

    template <bool B> struct other {
        typedef int value;
    };
    

    Here, your program would be ill-formed because other<b>::value is a type, not a value, but the compiler couldn't diagnose the error without actually doing the instantiation.