0

So I'm trying to concatenate an enum to an std::string. For this I wrote the following code.

typedef enum  { NODATATYPE = -1, 
            DATATYPEINT, 
            DATATYPEVARCHAR
          } DATATYPE; 
inline std::string operator+(std::string str, const DATATYPE dt){
  static std::map<DATATYPE, std::string> map;
  if (map.size() == 0){
    #define INSERT_ELEMENT(e) map[e] = #e
            INSERT_ELEMENT(NODATATYPE);     
            INSERT_ELEMENT(DATATYPEINT);     
            INSERT_ELEMENT(DATATYPEVARCHAR);     
    #undef INSERT_ELEMENT
  }   
  return str + map[dt];
}

and

DATATYPE dt1 = DATATYPEINT;
std::string msg = "illegal type for operation" + dt1;

I'm getting the following warning compiling this code.

warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: std::string msg = "illegal type for operation" + dt1; absyn.cpp:642:55: note: candidate 1: operator+(const char*, long int) In file included from file.cpp:4:0: file.h:18:20: note: candidate 2: std::string operator+(std::string, DATATYPE) inline std::string operator+(std::string str, const DATATYPE dt){

What does this warning exactly mean, and how to solve it?

Wouter
  • 652
  • 2
  • 7
  • 27
  • DATATYPE is of a type int, this means, that the compiler cannot distinguish, what should be called. You could try to use enum class from C++11. – UldisK Jan 05 '15 at 10:27
  • not getting any error http://ideone.com/Xsggwz – Ankur Jan 05 '15 at 10:33
  • Instead of using a map I would recommend some static auxiliary structure to go along with your enum and a `to_string` function as described here http://stackoverflow.com/questions/9150538/how-do-i-tostring-an-enum-in-c/9150607#9150607 – pmr Jan 05 '15 at 11:50

1 Answers1

2

What you pass to the operator is a const char* (to a string literal) and a DATATYPE. Since there is no overload operator+(const char*, DATATYPE), the compiler looks for overloads where the parameters can be implicitly converted. The candidates are in the warning:

operator+(const char*, long int)
operator+(std::string, DATATYPE)

The first parameter can be converted from const char* to std::string or the second parameter can be converted from DATATYPE to long int. So the first overload "wins" the overload resolution on the basis of first parameter and the second overload "wins" on the basis of the second argument. Since there is no overload that "wins" the resolution on the basis of both arguments, they are ambiguous.

The compiler warns you because it suspects that it may have chosen different overload than what you meant to call. If you compile with -pedantic on gcc you'll get error: ambiguous overload for... instead of just a warning.

The solution is to disambiguate the call by passing parameters of types that match exactly. A simple way would be:

std::string msg = std::string("illegal type for operation") + dt1;

or nicer in c++14

std::string msg = "illegal type for operation"s + dt1;
eerorika
  • 232,697
  • 12
  • 197
  • 326