Overload operator with template, but prevent redefinition

Viewed 177

I want to define specialization of operator<< using a template, but I don't want it to break the behavior of this operator if it's already defined for some data type.

enum State {Open, Locked};
enum Input {Coin, Push};

std::string ToString(State c){
  switch (c) {
    case Locked : return "Locked";
    case Open : return "Open";
  }
}

std::string ToString(Input c){
  switch (c) {
    case Coin : return "Coin";
    case Push : return "Push";
  }
}

template<typename T>   //obviously, a bad idea
std::ostream& operator<<(std::ostream& s, T c) {
  return s<<ToString(c);
}

later in code I'd like to use:

int main() {
  std::cout<<Coin<<std::endl;
  std::cout<<Open<<std::endl;
  std::cout<<std::string("normal string")<<std::endl;
}

Unsurprisingly, above gives compilation error:

error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::string {aka std::basic_string<char>}’)
   std::cout<<std::string("normal string")<<std::endl;

(many more follow)

Q: How to tell the compiler to ignore template, if the function / operator already has a definition?

3 Answers
Related