TruthSeeker
TruthSeeker

Reputation: 1579

Why const char* implicitly converted to bool rather than std::string?

#include <iostream>
#include <string>

struct mystruct{
     mystruct(std::string s){
        
        std::cout<<__FUNCTION__ <<" String "<<s;
    }
    
     explicit mystruct(bool s) {
        
        std::cout<<__FUNCTION__<<" Bool "<<s;
    }
};


int main()
{
    
    const char* c ="hello";
    
    mystruct obj(c);

    return 0;
}

output:

mystruct Bool 1
  1. Why const char* implicitly converted to bool rather than std::string, though constructor requires explicit type ?
  2. How the implicit conversion priority applies here?

Upvotes: 16

Views: 1690

Answers (3)

Bruce Adams
Bruce Adams

Reputation: 5589

Just to add to the already good answer. You can work around this by adding a delegating constructor as in:

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

Which will win over bool in overload resolution.

Another option is to avoid bool here and use a bool but something that carries more meaning. This could be an example of 'boolean blindness'

Upvotes: 0

Itachi Uchiwa
Itachi Uchiwa

Reputation: 3164

"Why const char* implicitly converted to bool rather than std::string, though constructor requires explicit type ?":

  • Standard conversion is preferred over user defined-conversions.

char const* is a pointer to constant character and a pointer can be implicitly converted to bool : in case it is nullptr it is converted to false otherwise to true.

  • You used to see such effective conversion in conditions where you check whether the pointer is NULL or not so in case it is not nulptr we safely de-reference it otherwise it has nullptr value thus it is not correct to de-reference it:

    int* ptr = nullptr;
    
    if(ptr) // false  because ptr has nullptr or NULL or 0 or 0x000000 address value
       std::cout << ptr << '\t' << *ptr << '\n'; // not executed
    
    ptr = new int(10); // valid and non-nullptr
    
    if(ptr) // non-nullptr so condition succeeds
       std::cout << ptr << '\t' << *ptr << '\n'; // 0FED155   10
     delete ptr; // free memory
    
  • explicit constructor means it can only be called explicitly and the only way is through Direct Initialization like in your case:

    mystruct obj(c); // direct initialization
    mystruct obj = c; // copy-initialization. Error: constructor myStruct(bool) is `explicit`
    

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172984

Because the implicit conversion from const char* to bool is qualified as standard conversion, while const char* to std::string is user-defined conversion. The former has higher ranking and wins in overload resolution.

A standard conversion sequence is always better than a user-defined conversion sequence or an ellipsis conversion sequence.

BTW: mystruct obj(c); performs direct initialization, explicit converting constructors including mystruct::mystruct(bool) are considered too. As the result, c is converted to bool then passed to mystruct::mystruct(bool) as argument to construct obj.

Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.

About explicit specifier,

  1. Specifies that a constructor or conversion function (since C++11) or deduction guide (since C++17) is explicit, that is, it cannot be used for implicit conversions and copy-initialization.

Upvotes: 17

Related Questions