//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.
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;