Search code examples
c++operator-overloadingtemplate-specialization

<< operator overloading and template specialization


As part of study purpose, I was just playing with template specialization together with operator overloading

#include <iostream>

template<class T>
void operator<<(std::ostream& COUT,T val)
{
   std::operator<<(COUT,val); //works for basic data types
}

//specializing for const char*
template<>
void operator<<(std::ostream& COUT,const char* val)
{
    std::operator<<(COUT,val);
}
int main()
{
    std::cout<<"samplestring"; //getting error here
    return 0;
}

I am getting following error which I cannot figure out.

<source>:17:14: error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'const char [13]')
   17 |     std::cout<<"samplestring";
      |     ~~~~~~~~~^~~~~~~~~~~~~~~~
      |          |     |
      |          |     const char [13]
      |          std::ostream {aka std::basic_ostream<char>}

what is the problem here

Thank you..!


Solution

  • The problem is there is already operator<<(std::ostream& COUT,const char* val) defined by the standard library.

    So now there are two symbols

    std::operator<<(std::ostream& ostream,const char* val);
    operator<<(std::ostream& COUT,const char* val); // YOURS
    

    Because the symbols are different, there are no multiple-definition errors.

    For a call std::cout << "Hello", the compiler searches for all operator<< functions currently defined at the call site. That looks like it is just your function, but the compiler also looks into all namespaces in which the passed arguments are defined. In this case it is std:: namespace and there the compiler finds the STL version. That is called argument dependent lookup(ADL).

    Since both functions are templates and neither is more specialized than the other, the call is ambiguous.

    Please do not use all capital letters as variable COUT, that is usually reserved for macros, with one-letter template parameters being exception T.

    //works for basic data types

    That is also not true, std::cout<<5; will NOT call your definition with T. Because there exists std::ostream::operator<<(int v) method. Same lookup happens but since this method is not a template, it is a better candidate and thus chosen. Your template function is never called.