Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?
like image 658
TruthSeeker Avatar asked Mar 03 '21 07:03

TruthSeeker


People also ask

What is the difference between const char * and string?

1 Answer. Show activity on this post. string is an object meant to hold textual data (a string), and char* is a pointer to a block of memory that is meant to hold textual data (a string). A string "knows" its length, but a char* is just a pointer (to an array of characters) -- it has no length information.

What is implicit conversion in c++?

An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.

What is a const char?

const char* is a mutable pointer to an immutable character/string. You cannot change the contents of the location(s) this pointer points to. Also, compilers are required to give error messages when you try to do so. For the same reason, conversion from const char * to char* is deprecated.

Why do we use const char?

If you don't have the choice, using const char* gives a guarantee to the user that you won't change his data especially if it was a string literal where modifying one is undefined behavior. Show activity on this post. By using const you're promising your user that you won't change the string being passed in.

What does @const char* is converted to bool?

const char* is no more converted to bool. This time it's converted to string and this is the new output: This indicates that variant tries to convert other types first to bool and then to string.

Is it safe to convert a string to a bool?

When std::string was designed, neither of these was present though. That made classes that supported conversion to bool fairly difficult to keep safe. In particular, that conversion could (and would) happen in lots of cases you almost never wanted it to.

Is there a built-in conversion from const char to INT?

Before trying to use user-defined conversions (remember that std::string is a user-defined class for this purpose), the compiler will try built-in conversions. There is no built-in conversion from const char* to int, but according to §4.12 in the standard:

Can boost variant accept const char* and convert it to bool?

I have declared a boost::variant which accepts three types: string, bool and int. The following code is showing that my variant accepts const char* and converts it to bool. Is it a normal behavior for boost::variant to accept and convert types not on its list? const char* is no more converted to bool.


2 Answers

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.
like image 159
songyuanyao Avatar answered Oct 19 '22 02:10

songyuanyao


"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`
    
like image 1
Itachi Uchiwa Avatar answered Oct 19 '22 02:10

Itachi Uchiwa