C++: avoid automatic conversion of string to bool in overloads

老子叫甜甜 提交于 2019-12-11 00:37:34

问题


I want to create a set of methods that will output a value with special formatting based on its type. When I'm doing it this way, it looks so far so good:

static void printValue(std::ostringstream& out, int value) {
    out << value;
}

static void printValue(std::ostringstream& out, double value) {
    out << value;
}

static void printValue(std::ostringstream& out, const std::string& value) {
    out << "\"" << escapeString(value) << "\"";
}

Testing:

printValue(std::cout, 123);    // => 123
printValue(std::cout, 3.14);   // => 3.14
printValue(std::cout, "foo");  // => "foo"

However, as soon as I add bool overload:

static void printValue(std::ostringstream& out, bool value) {
    out << (value ? "true" : "false");
}

... things break, as bool-based overload seems to be used by default by add string invocations:

printValue(std::cout, 123);    // => 123
printValue(std::cout, 3.14);   // => 3.14
printValue(std::cout, true);   // => true
printValue(std::cout, "foo");  // => true <= !!!

Is there any way I can escape this automatic cast-to-bool and force compiler to choose a correct method for strings?


回答1:


You could add an template overload that takes a reference to array of char of size N where N is a template parameter, and/or one that accepts a const char*.

template <std::size_t N>
static void printValue(sts::ostringstream& out, const char (&str)[N])
{
    out << str;
}



回答2:


Why this happens:

When the compiler is trying to choose the "best" function to call given some arguments, it prioritizes the overload set in roughly this way:

  1. Exact match: For example, if you pass a const char* and the function accepts a const char*, that's great
  2. Standard conversion sequences: For example, converting a const char[4] to a const char* and then a const char* to bool (based on a check for nullptr). Or promoting a short to an int
    • These conversions also have their own prioritization that we can ignore for the sake of brevity
  3. User defined conversions: basically, conversion to some non-fundamental type (via constructor or conversion operator)

Because you are providing a character literal "foo" it has a standard conversion sequence from const char[4] to const char* (via array to pointer conversion, see [conv.array]) and then from const char* to bool via boolean conversion (see [conv.bool]).

So, while it is possible to construct a const std::string& with "foo" via a user defined conversion, such a conversion is of lower precedence than the standard conversion sequence, and thus the boolean is chosen.

What you can do:

  • Anticipate this and write an overload for const char* or const char[N] like @juanchopanza said
  • create a std::string when you call the function: printValue(std::string{"foo"});


来源:https://stackoverflow.com/questions/53709105/c-avoid-automatic-conversion-of-string-to-bool-in-overloads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!