
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<>). If we can not live without them, we could always try to do whatever is better. Vicente, you are not serious, right?.. It is just that you did not like/agree with my "reasoning" and, so you suggested something unreasonable (IMO) and presented it as a "consequence" of my "reasoning" just to indicate how ridiculous mine was... Was that the idea?... Or I am misunderstanding you post? 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. I cannot live without implicit T to optional<T> and prohibiting it will break tonnes of my code and project code and Fernando Cacciola's code (if I remember our similar discussions years ago)... and it'll break all that code *now*... no need to wait and see... and "selling" optional<T> without implicit T to optional<T> will be real hard... in my neck of the woods anyway.
I understand your backward compatibility concern? I'm not suggesting at all to change boost::optional. I'm looking on how all these conversions can be made safer. You surely remember my Boost.Conversion proposal that was rejected. I believe that there is something interesting behind this idea. 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. Boost.Conversion was a library proposal. We could rethink it as a language proposal. 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 ] 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)); } 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) ) 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 } This operator could be used also to mean the empty set, as in set<int> f { ... return []; }; Another example variant< int, string> f(int x) { if (x > 10) return [ std::string("___") ]; else return [ x + 1 ]; } Indirectly Herb Sutter proposal [n4074] "Let return {expr} Be Explicit" and Gor Nishanov [4134] Resumable functions proposal interact with this implicit explicit conversion thing. I don't know how to implement in C++14 the mreturn Haskell Monad m =>mreturn :: a -> m a as C++14 doesn't consider the context of the call and so the m can not be deduced. I hope it is clear now that I don't want to change optional but see what the safer optional could be with the ongoing C++ proposals. Best, Vicente