Search code examples
c++templatesconstructordefault

Template function default parameter


//template.h using MSVC++ 2010
#pragma  once
#include <iostream>
using std::ostream;
template <typename T, typename U> class Pair {
  private:
    T first;
    U second;

  public:

    // Pair() ;
    Pair ( T x = T() , U y = U() ) ;
    template<typename T, typename U> 
    friend ostream& operator<< ( ostream& thisPair, Pair<T, U>& otherPair );

};
template <typename T, typename U> 
Pair<T, U>::Pair ( T x , U y ) : first ( T ( x ) ), second ( U ( y ) ) 
{cout << x << y;}

template <typename T, typename U> 
ostream& operator<< ( ostream& os, Pair<T, U>& otherPair )
{
    os << "First: " << otherPair.first 
<< " "<< "Second: " << otherPair.second << endl;
    return os;
}

//template.cpp
int main()
{
    int a = 5, b = 6;
    Pair<int,int> pair4();
    Pair<int, int> pair1 ( a, b );
    cout<<pair4;
    cout<<pair1;
    return 0;
}

How to make a constructor or a member function to take default value? The code above is giving linker error for pair4 when using cout statement. The code works perfectly when cout<<pair4(); is commented. I am trying to mimic a constructor taking 0,1 or 2 argument using a single default constructor in a template class.


Solution

  • Apart from other errors like shadowing template parameters (which MSVC++ wrongly ignores), the problem is here:

    Pair<int,int> pair4();
    

    This declares a function instead of a variable. This is because it can be syntactically both and C++ standard selects the most vexing parse: anything that can be interpreted by compiler as a declaration, will be interpreted as a declaration. The linker error then is that you try to print to cout address of a function that is never defined (has no address).

    Side note: in GCC and Clang, you can actually link this because the address is immediatelly converted to bool for operator << (there is no operator for printing function pointers to ostream and bool is the only available implicit conversion) which will always result in true (address of a declared function can never be nullptr) so the address itself is optimized away.

    The fix is very simple:

    Pair<int,int> pair4;