c++templates

Choosing between template instantiation with pointer arguments


Look at the following test code:

template<class T> struct Wrap {};

template<typename T> inline
void fun (T *&Int)          // **choice 1**
{}

template<typename T> inline
void fun (Wrap<T> *&Int)    // **choice 2**
{}

int main()
{
  int i = 6;
  fun((char*&)(i));         // **call 1**
  fun((Wrap<char>*&)(i));   // **call 2**
}

When I run this code in linux g++, it works as per expectations. When fun() is called with char*&, it calls function of choice 1 straight forward. However, I am interested when we call fun() with Wrap< char >*& and it calls the choice 2. Even though choice 1 and 2 both appear valid for the 2nd call, compiler manages to choose little better contender -> choice 2 (because it exists).

Question: Is it guaranteed that, the same behavior will be retained for any other compiler for C++ ? If not, then is there any other alternative to make it deterministic?


Solution

  • While the code might look like a template specialization, that is not the case. The language does not allow for partial template function specializations. The two are unrelated templates that happen to be overloads.

    The compiler will lookup up the call to fun( (Wrap<char>*&) i ) with the usual lookup mechanisms, will find the two templates and will determine that there are two potential overloads:

    template <typename T> void fun( T*& );      // with T == Wrap<char>
    template <typename T> void fun( Wrap<T>*& ) // with T == char
    

    Overload resolution will then determine that the second is a better match and instantiate it. This is guaranteed by the standard, but beware: they are not the same template, but rather different templates and you might run into undexpected results. Look at the article @LiKao linked for more insight.