
Le 26/11/14 06:26, Vladimir Batov a écrit :
... 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
Vicente Botet wrote 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