An explicit constructor of the wrong type, called

In the following example, my output is "single param ctor", twice. My question is twofold: firstly, why the call to bool ctor and not the version containing the string, and secondly, is there a way to get the version of the string without calling the call?

Aside, my actual code does not call constructors with hard-coded strings, but with something like:

static constexpr auto NONE = "NONE"; Foo aFoo(NONE); 

...

 #include <iostream> #include <string> using namespace std; struct Foo { explicit Foo(bool _isVisible = false): id(""), isVisible(_isVisible) {cout << "single param ctor" << endl;} explicit Foo(const string _id, bool _isVisible = false): id(_id), isVisible(_isVisible) {cout << "multip param ctor" << endl;} const string id; bool isVisible; }; int main(int argc, const char * argv[]) { shared_ptr<Foo> sharedFoo = make_shared<Foo>("hello"); Foo regFoo("hi"); return 0; } 
+7
c ++ constructor c ++ 11 c ++ 14
source share
2 answers

This is a C ++ restriction inherited from older C ++ and ultimately from C.

Your string literals convert to bool better than to the "custom" type std::string .

Instead of casting in the call, you can add a constructor that accepts const char* , perhaps delegating your existing constructor that accepts std::string :

 explicit Foo(const char* _id, bool _isVisible = false) : Foo(std::string(_id), _isVisible) {}; 

This constructor will be an “exact match” (or quite close at all) and will not allow bool to steal the spotlight.

Or, since C ++ 14 uses the literal std::string instead of cast, for example. "hi"s , although you should keep this in mind in callsite, which is "meh" for a general solution.

By the way, if , you really want to take your parameter std::string _id by value, do not make it const ; you stop him from moving and requesting a copy in the member initializer. Depending on what happens on your regular call site, the following may make more sense:

 explicit Foo( string _id, bool _isVisible = false ) : id(std::move(_id)) , isVisible(_isVisible) {} 

If you usually pass in lvalue, although at least accept const std::string& to prevent one copy.

+8
source share

why bool ctor is called and not the version containing the string

Since "hi" is a pointer to a char array of characters, which is converted to a pointer to a char (thanks, Lightness Races in orbit), so the number I converted to bool.

Is there a way to get the version of a string without calling a call?

Not very elegant, but ... you can pass a second boolean parameter

 Foo regFoo("hi", false); 

to exclude the first constructor

0
source share

All Articles