Le 28/11/14 20:22, Gottlob Frege a écrit :
On Thu, Nov 27, 2014 at 8:08 PM, Vicente J. Botet Escriba
wrote: 0 - std::less should be same as op< (I think we all agree here, actually, which is why we should have std::order) Only if op< id defined. Do you mean only *the same* if op< is defined, or only *exists* if op< is defined? op
or, technically, pointers) do you still want std::less?
std::less
1 - op<(optional<T>, optional<T>) is "sensible" but somewhat arbitrary
I don't agree here. We don't need anything arbitrary. op
is defined. It is arbitrary in the sense of where "none" is ordered.
Agreed. we have decided that optional<T> is some way none_t+T and not T+none_t.
I (strongly!) agree with the only if op<(T,T> is defined. (And famously believe op>=(optional<T>,optional<T>) should be based on op>=(T,T), instead of !op<(T,T) )
Agree again.
2 - op<(optional<T>, T) is questionable, often (usually?) wrong Agreed. 3 - in general, func(optional<T>, optional<T>) should work if passed T's (ie implicit conversion is important) I have my doubts here. Implicit conversions provide often (usually?) unexpected behavior. I think we need a general guideline for the std library for when implicit is OK. ie Is it OK for dumb_ptr? string_view? etc. That's something I'd like to work on. I _think_ there is a general guideline, but maybe it is too case-by-case?
We have worked a lot with implicit conversion as C++98 did have explicit ones. I would say that the conversion should be explicit by default. Implicit conversion should be allowed only when there is a sub-type relationships <: between the types. This sub-type relationship should satisfy: Anti-symetric: If we have types R, S such that R <: S with implicit conversions from R to S , the conversion from S to R can not be implicit (no implicit cycles), however there should be an explicit conversion from S to R (coercion). Transitivity: If we have types R, S, T such that R <: S <: T with implicit conversions from R to S and from S to T, there should be also an implicit conversion from R to T. That is R <: T. Note that C++ conversions are not transitive. Identity: R ° S = identity If we have types R, S such that R <: S For any r:R R(S(r)) == r. That is, there is no loss of information. Efficiency The cost of the implicit conversion from the subtype to the super type is almost null. Conversions that implies a high conversion cost must be explicit. Refinement The conversions from/to the super type must be defined on the sub-type (this is in line with OO sub-typing, we can refine, but not generalize). Defining implicit conversion on the super-type side would invalidate valid programs. If we had class S void f(S); and now we define a subtype R of S, R <: S, with an implicit conversion from R to S. R r; f(r); // well formed Now if we define a super type of T fo S, S <: T, that defines implicit conversions from S to T and from R to S, and add a generalization for f void f(T); The previous program would not be any more well formed R r; f(r); // ambiguous conversion f(S) and f(T) That is, super typing is not allowed. This point should be the most controversial, but I think it is the most important :(
Currently we have std::less, not std::order and the STL ordered containers are using as default comparator std::less. So let define std::less
using std::less<T>. Yes. We currently have that much - std::less
is built with std::less<T>, not op<(T,T). Even if only for the sake of pointers. On almost-non-existent hardware, (and maybe future hardware).
I'm missing the wording for the definition of std::less