MadOgre
MadOgre

Reputation: 541

Is there any possible way to force implicit constructor initialization with a string literal

Suppose I have a class

class Foo
{
public:
    Foo(int x);
    Foo(std::string s);
}

I want to be able to initialize objects like this

int main()
{
    Foo f1 = "some string"
}

rather than

int main()
{
    Foo f1("some string");
}

So far I am getting a compiler error: error: invalid conversion from 'const char*' to 'int' [-fpermissive]|

All I can think of is making an additional constructor that takes char* argument, but I was hoping to avoid this redundancy.

Upvotes: 2

Views: 130

Answers (1)

While it might not seem obvious, there are two user defined conversions in the case of copy-initialization:

Foo f1 = "some string";

In the expression above, Foo f1 = is a call to Foo(Foo const &) with the right hand side as argument. For that, the compiler would need to figure out how to go from literal (array of N char) to Foo, and that requires a user defined conversion to std::string (contructor taking const char*) and a second user defined conversion from std::string to Foo (second constructor above).

Now, it might not seem obvious why the second case does not require the same number of conversions… when you do Foo f("something"); the compiler considers the three overloads:

Foo(int);
Foo(std::string);
Foo(Foo const &);

There is no conversion from literal to int, so the first is discarded. There is a one-step conversion from literal to std::string (by means of the constructor taking const char*) so this is a viable candidate. As seen above, there is no one-step conversion from literal to Foo, so that one is also discarded and the only viable candidate is picked up.

The language is quite clear in that there can only be on user defined conversion in a conversion sequence, so there is nothing that can be done there. So you are left with either providing another constructor or making sure that the right hand side is a std::string. For that you could either explicitly convert (valid in C++03):

Foo f1 = std::string("something");

You might also just leave this to the user and require that they do direct initialization instead of copy initialization. Or you can add a constructor that takes the const char*.

Upvotes: 2

Related Questions