Search code examples
c++stringstloverloadingdelegating-constructor

C++: choosing a `const char *` vs `std::string` when using delegating constructor


Consider the following:

class Foo {
public:
    Foo (const char *in) {
        printf ("C string constructor called\n");
    }
    Foo (std::string const &in) : Foo(in.c_str()) {
        printf ("C++ string constructor called\n");
    }
};
Foo bar ("I never asked for this");
//C string constructor called

So, a constant string is treated as a const char * one.

But what would change, if we make a std::string constructor "primary"?

Can we expect that an std::string object would be created and passed to corresponding constructor without calling a C-string related one?

class Foo {
public:
    Foo (std::string const &in) {
        printf ("C++ string constructor called\n");
    }
    Foo (const char *in) : Foo(std::string (in)) {
        printf ("C string constructor called\n");
    }
};
Foo bar ("I never asked for this");
//C++ string constructor called
//C string constructor called

Again, the C-string constructor was called first.

Is this behavior described in C++ standard, or is it compiler-related?

Would this work the same way for e.g. templates or overloaded functions?

I compiled with GCC 7.3.0 (MSYS2 x64).


Solution

  • "I never asked for this" is a string literal which consists of const char elements:

    Foo bar ("I never asked for this"); // calls Foo (const char *in)
    

    Thus, Foo (const char *in) will always get selected by overload resolution regardless of the "order" in which you declare your constructors.

    As seen in your 2nd example,

    Foo (const char *in) : Foo(std::string (in))
    

    The delegating constructor is selected and will call the target constructor, as selected by the only member of the initialization list.