ryan0270 ryan0270 - 2 months ago 6
C++ Question

Compiler is trying to initialize enum class from int when it shouln't

I have an enum class of types and want a "to_string" function for outputting the type name so I wrote that inside my own namespace. Problem is, other functions in that namespace trying to call to_string on, e.g., an int (really just an int, not intended to be part of the enum) are finding the custom to_string and giving errors about invalid initialization of the enum.

I know I could explicitly call std::to_string instead of to_string but I assume there's a better way. What am I doing wrong?

Here is example code:

#include <iostream>
#include <string>

namespace other {
enum class Type {

std::string to_string(const Type& type) {
switch(type) {
case Type::Type1:
return "Type1";
case Type::Type2:
return "Type2";

return "Unknown";

void run() {
using namespace std;
cout << string("Type: ") + to_string(Type::Type1) << endl;
cout << string("int: " ) + to_string(42) << endl; // this one generates compile-time errors

int main() {

using namespace std;
cout << string("int: " ) + to_string(42) << endl; // This one is ok

return 0;


This is a tricky situation which involves some subtle rules of namespaces. Let's consider a simpler example:

namespace b {
  void f(int) { }

namespace a {
  using namespace b;

  void f(char) { }

  void g()
    f(5); // calls f(char)

The issue here is that even though we have "using namespace b", the declarations inside b are treated as if they were declared in the common namespace (global) for the purposes of lookup:

(C++14 7.3.4/2)

A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, “contains” means “contains directly or indirectly”. — end note ]

Because of this, for the purposes of lookup, the names in namespace b are treated as if they were in the global namespace. That means f(char) inside namespace a will hide f(int) inside namespace b:

(C++14 3.3.10/4)

During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive can be hidden by declarations with the same name in the namespace containing the using-directive; see (

In your example, a call to to_string(42) in other::run() will find other::to_string, because std::to_string(int) is hidden.