Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I construct optional<T> with an optional<S> (for S!=T)?

If we have

 std::experimental::optional<int> x;

neither of the following lines compiles:

 std::experimental::optional<unsigned int> y; y = x;
 std::experimental::optional<unsigned int> z(x);

... even though it seems to me to make sense just like an assignment of an int to an unsigned int. Why shouldn't this work? That is, what is the pitfall that is avoided by the library not implementing the copy ctor and the assignment operator for such cases?

like image 881
einpoklum Avatar asked May 02 '16 12:05

einpoklum


1 Answers

You can't do that, because std::experimental::optional has no appropriate overload for constructor and assignment operators.

It would certainly be possible to provide such interface. In fact, boost optional, which the proposed interface is based on, does have an overloaded constructor and assignment operator for constructing from another instance of optional.

The proposal, has a section "Comparison with Boost.Optional" which contains a comparison table which includes discussed overload. The proposal doesn't give justification for the differences except for the general statement:

The current proposal reflects our arbitrary choice of balance between unambiguousity, genericity and flexibility of the interface.

The rationale for the descision of whether to include the overloads is discussed in the git repo that has the reference implementation and in ISO C++ Standard - Future Proposals mailing list.

In the github issue, Andrzej Krzemieński, an author of the proposal, show this problematic ambiguity that the overload may cause:

It is just not clear what should happen in the following situation:

struct Tool
{
  Tool(int); // ctor 1
  Tool(optional<int>); // ctor 2
};

optional<int> oi = 1;
optional<Tool> ot = oi;

Which constructor of Tool should be called and why?

like image 114
eerorika Avatar answered Nov 13 '22 18:11

eerorika