I understand people like implicit constructors until they find that they don't want them here or there.
void f(optional<T>); T x; f(x);
Later on add void f(expected<T>); T x; f(x); // ambiguous :(
This is fine. It's a compile time error. Writing f(expected<T>(x)) eliminates the ambiguity.
So T is a subset of two sets and then we need to be explicit. Been explicit from the beginning avoids surprises.
This is just a compile-time surprise, so this is not all that bad. But you may get a run-time surprise
vector<T> x; void f(expected<vector<T>>);
f(x); // are you aware that you are copying a vecotor?
If people fail to use std::move, they should always assume a copy. Except when returning from a function. f(std::move(x)) would do the right thing here I believe.
Maybe no-one uses expected<T> as function parameter, but consider this:
expected<vector<T>> g() { vector<T> v; // try to populate v; return v; // are you expecting a copy elision here? }
This is definitely a concern for C++ 14 (not 17). But I think end users get this problem with implicit conversion - it helps that recent clangs have a rich set of warnings when you do an inefficient return of a stack allocated object. So I don't think it as much a problem as others think.
Even if we wanted that expected<T,E> is valid only if T is different from E, I believe the explicitness has added value.
Throughout AFIO v2, I not only **always** return via make_valued_result or make_errored_result, I found myself specifying the return type too e.g. make_valued_result<io_state>(s); But imposing that on users so they have no choice ... that I don't agree with for a Boost library. I am much less concerned with a STL type admittedly, there I'd live with always explicit construction. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/