user1556435
user1556435

Reputation: 1056

boost::optional<std::string> and implicit constructor from char[]

I have got used to initializing std::strings in the following way by letting the compiler figure out the magic involved

std::string my_string = "hello";

The following will not work as there is no explicit conversion between the two types:

boost::optional<std::string> my_optional_string = "hello";

This however does work:

boost::optional<std::string> my_optional_string = std::string("hello");

Now, would there be no way to daisychain the implicitly called single-arg constructors to allow the second form? The reason I ask (I don't want to bother you with details though) is that there are a whole bunch of classes with optional members to be populated. Having to explicitly type everything seems a burden (I do not so much worry about myself, but I am working on an open source API and would like to provide as much comfort to my users as possible). Any suggestions are appreciated.


Edit: Sorry guys I am new to this, should have provided more clarifying code examples. I have some classes (not modelled myself, just implemented them in C++) with optional members to be populated, like this:

Class Class1 {
public:
    Class1(const boost::optional<std::string>& arg_1, /*... ,*/ const boost::optional<std::string>& arg_n );
};

What I'd like my API users to be able to specify is:

Class1 my_class("hello","there",NULL,"stackoverflow");
/* ( Note: NULL is actually risky here, as some classes might also have members of type boost::optional<int> ) */

And not:

Class1 my_class(std::string("hello"),/*or*/boost::optional<std::string>("there"),boost::optional<std::string>(),std::string("stackoverflow"));

Thanks again.

Upvotes: 6

Views: 6886

Answers (2)

Jesse Good
Jesse Good

Reputation: 52405

Since the constructor is marked explicit, why don't you call the constructor explicitly? boost::optional<std::string> my_optional_string("hello");

After Edit

Xeo already provides the solution, perhaps you could also use default arguments for your constructors:

Class1(boost::optional<std::string> = boost::optional<std::string>(), /*...*/)
Class1(std::string arg1, /*...*/) : 
member1(arg1), /*member2(arg2), etc.*/

Then you can all Class1 like this:

Class1 my_class;
Class1 my_class("hello", "there"); // Rest of arguments use boost::optional

But, if you have to provide many constructors and possibilities, perhaps the above might not be a good solution, you could look into templating it to cut down on how much code you have to write.

Upvotes: 7

Xeo
Xeo

Reputation: 131907

Easiest solution: Provide multiple constructors, one taking char const* or better std::string, and one taking boost::optional.

If you want this possibility for every argument by itself, it's way better to just template the ctor, though.

template<class A1, class A2, class A3 /*, ..., class AN*/>
Class1(A1 const& a1, A2 const& a2, A3 const& a3 /*, ... , AN const& aN*/)
  : _member1(a1)
  , _member2(a2)
  , _member3(a3)
/*, ...
  , _memberN(aN)*/
{ /* ... */ }

Btw, you shouldn't pass NULL for a non-used optional, but boost::none.

Upvotes: 1

Related Questions