This might be not as flexible as would want. Use typedef with explicit type instanciation. It might require some extra work for using it, but it is usually small indeed:
using namespace std;
template<typename T> struct cfoobar
{
struct cgoobar {};
};
template<typename T, typename charType = char>
basic_ostream<charType>& operator <<
(basic_ostream<charType>& os, const cfoobar<T>&)
{
os << "overload 1:" << __FUNCSIG__; return os;
}
typedef cfoobar<int>::cgoobar int_cgoobar;
template<typename charType = char>
basic_ostream<charType>& operator <<
(basic_ostream<charType>& os, const int_cgoobar& c)
{
os << "overload 2:"<< __FUNCSIG__; return os;
}
int main()
{
cout << cfoobar<int>{} << endl;
cout << int_cgoobar{} << endl;
return 0;
}
Potential problem are expected with the way you are using using
ostream which is already defined in iostream. Use a different name, for instance
os
template<typename T, typename charType = char>
basic_ostream<charType>& operator << (basic_ostream<charType>& os, const cfoobar<T>&) { os<< __FUNCSIG__; return os; }
template< typename T, typename charType = char>
basic_ostream<charType>& operator << (basic_ostream<charType>& os, const int_cgoobar& c) { os<< __FUNCSIG__; return os; }