Overloaded Bool / String Ambiguity

Why does C ++ literate a string literal that I pass as bool and not a string?

#include <iostream> using namespace std; class A { public: A(string v) { cout << v; } A(bool v) { cout << v; } }; int main() { A("hello"); return 0; } 

Output: 1

Is this because the compiler is not smart enough to make the transition from char * to string and rather just assumes bool is the closest thing to a pointer? Is the only option for creating an explicit char * constructor that basically does the same thing as a string constructor?

+9
c ++ string casting overloading boolean
source share
4 answers

If you have C ++ 11, you can use the delegation constructor:

 A(char const* s) : A(std::string(s)) { } 

The reason the boolean conversion constructor is chosen compared to the one used for std::string is because the conversion from char const* to bool is a standard conversion, and one of std::string is a custom conversion. Standard conversions have a higher rank than custom conversions.

+13
source share

FROM

 A(string("hello")); 

he will give the expected result.

Why is this so?

This is due to standard conversions:

  • "hello" is understood as a const char* pointer
  • this pointer can be converted to bool (standard section 4.12: "The prvalue of (...) (...) property can be converted to a prvalue of type bool.")
  • the hi-to- string not considered, as the standard in Section 12.3 explains that “The type of transformation of class objects can be specified by the constructors and transformation functions. These transformations are called user transformations” and “User transformations are applied only where they are unique” . If you didn't have a bool constructor, std::string would be done implicitly.

How to get what you expected?

Just add the missing constructor for string litterals:

 A(const char* v) { cout << v; // or convert v to string if you want to store it in a string member } 

Of course, instead of rewriting the constructor from scratch, you can choose a delegate, as suggested by 0x499602D2, in another answer.

+3
source share

When choosing an overloaded method, this is the order that the compiler tries to execute:

  • Exact match
  • Promotion
  • Standard numeric conversion
  • User statements

The pointer does not advance to bool , but converts to bool . A char* uses the std operator to convert to std::string . Please note that if char* used the same number in this list to convert to bool and std::string , it would be ambiguous which method the compiler should choose, so the compiler would raise an "ambiguous overload" error.

I would throw my weight on the 0x499602D2 solution. If you have C ++ 11, it is best to call: A(char* s) : A(std::string(s)){} If you do not have C ++ 11, I would create the constructor A(char* s) and abstracted the constructor logic A(std::string) in the method and deduced this method from both constructors.

http://www.learncpp.com/cpp-tutorial/76-function-overloading/

+2
source share

I also went through this problem recently, let me share another way.

You can change the bool constructor to an unsigned char . Thus, the decomposition and implication of the conversion of the string literal does not occur, and the constructor std::string takes place.

 class A { public: A(string v) { cout << v; } A(unsigned char v) { cout << static_cast<bool>(v); } }; int main() { A("Hello"); // <- Call A(string) A(false); // <- Call A(unsigned char) } 

Thus, you do not need to always overload to std::string and const char* without creating a bloat code, creating std::string on the client call site.

I do not claim to be better, but it is easier.

+2
source share

All Articles