More converting constructors for Optional

129 views
Skip to first unread message

Andrzej Krzemieński

unread,
Oct 5, 2013, 1:14:05 PM10/5/13
to std-pr...@isocpp.org
Hi Everyone,
It was suggested by LEWG that the following converting constructor should be added to optional:

  optional<string> os = "str";
  optional<unique_ptr<Base>> op = unique_ptr<Derived>{};


and probably also this should work:

  optional<unique_ptr<Base>> op = optional<unique_ptr<Derived>>{};

At the same time the following should not be allowed:

  optional<unique_ptr<Base>> or = new Base{};

(because this would turn an explicit conversion into an implicit one). Such "conditionally explicit" converting constructor is doable, but I run on another problem. The additional constructors would look like:

  template <class U>
  optional::optional(U&& u);

  template <class U>
  optional::optional(optional<U> const& ou);

Suppose you have the following class:

  struct Port
  {
    Port (optional<int> oi);
  }; 

  optional<int> oi;
  optional<Port> op = oi;

which of the two constructors would the user expect to be called? I guess the former, but he would be surprised. I do not know how to solve this problem. Perhaps someone on the list does.

Regards,
&rzej

Ville Voutilainen

unread,
Oct 5, 2013, 1:33:01 PM10/5/13
to std-pr...@isocpp.org
On 5 October 2013 20:14, Andrzej Krzemieński <akrz...@gmail.com> wrote:

(because this would turn an explicit conversion into an implicit one). Such "conditionally explicit" converting constructor is doable, but I run on another problem. The additional constructors would look like:

  template <class U>
  optional::optional(U&& u);

  template <class U>
  optional::optional(optional<U> const& ou);

Suppose you have the following class:

  struct Port
  {
    Port (optional<int> oi);
  }; 

  optional<int> oi;
  optional<Port> op = oi;

which of the two constructors would the user expect to be called? I guess the former, but he would be surprised. I do not know how to solve this problem. Perhaps someone on the list does.


Depends on the user. Advanced users will know that the universal-reference ctor is a better
match since there's no const involved. Perhaps you could SFINAE it out in case the incoming
type is optional<U>?

Zhihao Yuan

unread,
Oct 5, 2013, 2:55:47 PM10/5/13
to std-pr...@isocpp.org
On Sat, Oct 5, 2013 at 1:14 PM, Andrzej Krzemieński <akrz...@gmail.com> wrote:
> Hi Everyone,
> It was suggested by LEWG that the following converting constructor should be
> added to optional:
>
> optional<string> os = "str";
> optional<unique_ptr<Base>> op = unique_ptr<Derived>{};
>
> and probably also this should work:
>
> optional<unique_ptr<Base>> op = optional<unique_ptr<Derived>>{};

I don't expect these to work. Within the optional
domain, we know T -> optional<T> is safe; but
outside this domain, it does not seem to be a good
idea to judge which kind of conversion is safe with
optional instead of just take the decision of C++.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://4bsd.biz/

Ville Voutilainen

unread,
Oct 5, 2013, 2:57:50 PM10/5/13
to std-pr...@isocpp.org
On 5 October 2013 21:55, Zhihao Yuan <z...@miator.net> wrote:
On Sat, Oct 5, 2013 at 1:14 PM, Andrzej Krzemieński <akrz...@gmail.com> wrote:
> Hi Everyone,
> It was suggested by LEWG that the following converting constructor should be
> added to optional:
>
>   optional<string> os = "str";
>   optional<unique_ptr<Base>> op = unique_ptr<Derived>{};
>
> and probably also this should work:
>
>   optional<unique_ptr<Base>> op = optional<unique_ptr<Derived>>{};

I don't expect these to work.  Within the optional
domain, we know T -> optional<T> is safe; but
outside this domain, it does not seem to be a good
idea to judge which kind of conversion is safe with
optional instead of just take the decision of C++.



Well, the LEWG guidance to explore these conversions was clear.

Zhihao Yuan

unread,
Oct 5, 2013, 3:04:03 PM10/5/13
to std-pr...@isocpp.org
On Sat, Oct 5, 2013 at 2:57 PM, Ville Voutilainen
<ville.vo...@gmail.com> wrote:
> Well, the LEWG guidance to explore these conversions was clear.

Add templated comparison operators?

SF WF WA SA
4 9 6 0

Find a way to enable mixed-type assigments

SF WF WA SA
7 6 6 1

Around 2:1. Be careful about "driven by straw polls"
or "design by committee".

Andrzej Krzemieński

unread,
Oct 5, 2013, 3:05:42 PM10/5/13
to std-pr...@isocpp.org

Oh, you spotted a different problem than I did. Mine was that (even if I fixed yours) it is not clear how to handle a case where T has a constructor taking another optional. Consider a more tricky type:

  struct Port
  {
    Port (optional<int> oi);
    Port (int);
  };

And now the code that uses it:


  optional<int> oi;
  optional<Port> op = oi;

Now, forget how optional is or might be implemented. As a user, which constructor of Port would you expect to be called?



Ville Voutilainen

unread,
Oct 5, 2013, 3:30:10 PM10/5/13
to std-pr...@isocpp.org
On 5 October 2013 22:05, Andrzej Krzemieński <akrz...@gmail.com> wrote:

Oh, you spotted a different problem than I did. Mine was that (even if I fixed yours) it is not clear how to handle a case where T has a constructor taking another optional. Consider a more tricky type:

  struct Port
  {
    Port (optional<int> oi);
    Port (int);
  };

And now the code that uses it:


  optional<int> oi;
  optional<Port> op = oi;

Now, forget how optional is or might be implemented. As a user, which constructor of Port would you expect to be called?


The one taking optional<int>, since optional doesn't automatically convert to an int. If you
have
int i;
optional<Port> op = i;
then I expect Port(int) to be used.

Andrzej Krzemieński

unread,
Oct 5, 2013, 3:38:50 PM10/5/13
to std-pr...@isocpp.org

Another (valid) expectation would be that constructor:

  template <class U> optional<T>::optional( optional<U> const& o );

does:

  if (o) { *(*this) = *o; }

in which case Port(int) would be used.
 

Ville Voutilainen

unread,
Oct 5, 2013, 4:39:12 PM10/5/13
to std-pr...@isocpp.org
Yes, good point, the optional part is indeed consumed by the converting constructor
of optional itself.
Reply all
Reply to author
Forward
0 new messages