function template with unused template parameter

  • A+
template<typename T> struct a  {    using type = int;   typename T::type i; };  template<typename T, typename = a<T>> void f1(T) {}  template<typename T, typename = typename a<T>::type> void f2(T) {}  int main() {   f1<int>(1); // ok   f2<int>(1); // error    return 0; } 

An instantiation of a<int> should be an error because int::type is illegal. But it seems that f1<int> can't cause the instantiation of a<T>, but f2<int> can. What's the reason?


When type is used as the template argument (including default template argument), it's not required to be complete type.

A template argument for a type template parameter must be a type-id, which may name an incomplete type:

So for f1, the default template argument is a<T> and it doesn't have to be complete. Given f1<int>(1); a<int> doesn't need to be instantiated.

But when you refer to the member of the class template, as the default template argument typename a<T>::type of f2, a<T> has to be complete type and then cause implicit instantiation.

When code refers to a template in context that requires a completely defined type, or when the completeness of the type affects the code, and this particular type has not been explicitly instantiated, implicit instantiation occurs. For example, when an object of this type is constructed, but not when a pointer to this type is constructed.

This applies to the members of the class template: unless the member is used in the program, it is not instantiated, and does not require a definition.

So given f2<int>(1);, a<int> will be instantiated and then cause the compilation error.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: