Boost logo

Boost :

Subject: Re: [boost] [optional] operator<(optional<T>, T) -- is it wrong?
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-11-26 12:56:00


Le 26/11/14 11:08, Rob Stewart a écrit :
> On November 26, 2014 2:12:56 AM EST, "Vicente J. Botet Escriba" <vicente.botet_at_[hidden]> wrote:
>> Le 26/11/14 06:26, Vladimir Batov a écrit :
>>> Vicente Botet wrote
>>>> ...
>>>> Following your reasoning, I will suggest to remove the implicit
>>>> construction from T to optional
>>>> <T>
>>>> and/or remove the
>>>> operator<(optional
>>>> <T>
>>>> , optional<>).
>>> Vicente, you are not serious, right?..
>> Vladimir, yes and not. Were talking of the possibility of a new
>> safe_optional. I would like we explore how we would like to have this
>> new type.
> [snip]
>
>> I'm looking on how all these conversions can be made safer.
> [snip]
>
>> The idea is to state explicitly that you want a explicit conversion but
>> don't state to what. The what is deduced from the context.
> That idea is rather odd to me. One is hardly being explicit if one is relying on context to determine the target type.
Well, you state explicitly that you allow the compiler to convert to the
target type, without repeating the target type. The compiler know
already it.
>
>> Let me represent by
>>
>> [ x ]
>>
>> this explicit conversion to the context.
>> With this we could be able to
>>
>> optional<int> f(int x) {
>> if (x<0)
>> return nullopt ;
>> }
>> return [ x ];
>> }
>>
>> [ x ] is longer than x but shorter than make_optional(x).
>>
>> The meaning of
>>
>> return [ x ]
> The target type is reasonably deduced to be the function return type, so this is a means to avoid repeating the type. auto would work as well: return auto(x);. That's on keeping with auto's purpose.

Glad to see you are for this use case. I'm not against return auto(x)
and the syntax, while important, is less important than th esemantic.
Has this been proposed/accepted/adopted already in the C++ standard?
>
>> on the context of a function returning M would be given by
>>
>> return M(x);
>>
>> We could also add an indirection and translate it to
>>
>> return make_explicitly(type<M>{}, x);
>>
>> or
>>
>> return type<M>{}[x];
>>
>> where the type<M> instance is used only to be able to overload on M.
>>
>> template <class T>
>> struct type {};
>>
>> The default implementation could then be a call to the explicit
>> constructor of the context from the parameter
>>
>> // default to explicit constructor
>> template <class M, class X>
>> M make_explicitly(type<M>, X && x) { return M(std::forward<T>(x)); }
> Using auto would be simpler.
I have no problem with the form.
>
>> We could stop here or we could use [ x ] not only on a return statement
>>
>> but also in any expression as in
>>
>> optional<int> oi;
>> int x;
>> ...
>> if ( oi < [x] )
>> ....
>>
>> Note that we don't need an implicit conversion from T to optional<T>
>> then but only an explicit one, avoiding the more verbose
>>
>> if ( oi < std::make_optional(x) )
> If anything in the expression or calling context changes, the target type can change. How is that explicit? It's no better than an implicit conversion. Indeed, it's worse: it bypasses the control implied by marking a constructor explicit.
Yes and not. If the expression oi < [x] has only a sens when [x] is
optional<int>, then what [x] is requesting is an explicit conversion
from x to optional<int>.
If the expression oi < [x] could be valid for more than one type T, the
expression is malformed.

If you don't want to depend on the context just be more explicit and use

   oi < std::make_optional(x)

There are a lot of situations, as is the case for the return type, on
which the context is unequivocally identified. In all these cases, the
use of [x] or auto(x) is useful.

>
>> This can be applied also on the context of the await proposal to
>> separate the concerns. await will take care of the the continuation
>> part
>> and {{}} will take care explicit conversion transformation.
>>
>> future<int> f(int x) {
>> if (x > 10)
>> return await something_long(x);
>> else
>> return [ x + 1 ]; // make_ready_future
>> }
> Use auto for the return statement.
Would a possible auto(x+1) let me translate it to make_ready_future(x)?

Hopping my comments help to clarify what I'm locking for.
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk