Closed viboes closed 10 years ago
What about "default"? I'm afraid we confuse this category with the "forward_iterator" category. Also the notion of forwarding here is a detail of implementation, the notion of "default" (or another name) explicitly state that it's the default behaviour. What do you think?
I'm open to other names, but "default" is not good for two reasons:
Sorry for the title, it should be, Should the default trait be defined?
Would "identity" be right? I think it's a good thing to define this default trait.
What we are implementing is forwarding, as we transform a non member function on one member function that has the same name and we forward the other arguments.
Why do you have problems with forward?
Well I don't really have a problem with it, it's just that it sounds really implementation-oriented and I was wondering if there was something more general underneath. But I'm ok with it.
Defaulting to forward would mean that any class supporting these functions syntactically would be be a model of the concept. A concept is much more than syntactic constraints and so an explicit mapping is desirable. The single thing the developer must do is to state it explicitly,e.g.
template <class T, class E>
struct errored_category<expected<E, T> > : mpl::identity<category::forward> {};
We could comeback to the default to forward if the model provide these member and or types as members, but the definition of the default is much complex. I implemented it just before deciding to add an explicit category. The code e.g. would be
template <class T, class = void>
struct value_traits_h : std::false_type {};
template <class T>
struct value_traits_h<T,
void_t<
typename T::value_type,
decltype(std::declval<T>().has_value()),
decltype(std::declval<T>().deref()),
decltype(std::declval<T>().value())
>
> : std::true_type {
// forward
};
This is needed if we want the valued_traits to be used SFINAE friendly. There are some proposals related to this SFINAE friendly, as result_of, common_type, iterator_traits. I think that these traits should also be SFINAE friendly.
Now we can use
template <class PV, class U, class = std::enable_if<valued_traits_t< PV >::value> >
constexpr value_type<PV> value_or(PV const& e, U&& v) {
return has_value(e)
? deref(e)
: static_cast<value_type<PV>>(std::forward<U>(v));
}
I have found a use for a category::default_
. Some concepts define a default implementation for some operations. This default implementations could be added to a xxxtraitscategory::default. E.g. in Haskell there is a mdo
operator(>>) that is defined as
template <class M, class T, class U>
apply<M,U> mdo(apply<M,T>&& m1, apply<M,U>&& m2)
{
return mbind(m1, [&](T& ) { return m2; });
}
Any xxx_traits
specialization could inherit from xxx_traits<category::default_>
.
What do you think?
Currently the value_traits forward all the operation fro the default category, that is the type itself. As a concept contains semantic constraints in addition of the syntactic ones, it would be better if the model designer states explicitly that the forward is correct way to map the type.
So I purpose to add a forward category and replace the default with this category.