
On 6/5/2015 6:23 AM, Peter Dimov wrote:
Eric Niebler wrote:
If a user defines a specialization for common_type<MyInt, int>, it won't get used when computing common_type<MyInt, int, int>. I think that would complicate your implementation somewhat.
It does. I now need a SFINAE-friendly defer in addition to eval_or_default.
// common_type
template<class...> struct common_type { using type_not_present = void***[]; };
template<class T> struct common_type<T>: std::decay<T> { };
template<class T1, class T2> using builtin_common_type = decltype(declval<bool>()? declval<T1>(): declval<T2>());
template<class T1, class T2> struct common_type<T1, T2>: mp_if_c< std::is_same<T1, std::decay_t<T1>>::value && std::is_same<T2, std::decay_t<T2>>::value, mp_defer<builtin_common_type, T1, T2>, common_type<std::decay_t<T1>, std::decay_t<T2>>> { };
template<class T1, class T2, class... T> using common_type_impl = common_type<typename common_type<T1, T2>::type, T...>;
template<class T1, class T2, class...T> struct common_type<T1, T2, T...>: eval_or_default<common_type<>, common_type_impl, T1, T2, T...> { };
mp_defer was before just
template<template<class...> class F, class... T> struct mp_defer { using type = F<T...>; };
but now has to be
// mp_defer
struct empty { };
template<template<class...> class F, class... T> struct mp_defer_impl { using type = F<T...>; };
template<template<class...> class F, class... T> using mp_defer = mp_if<is_evaluable<F, T...>, mp_defer_impl<F, T...>, empty>;
Now it's basically the same as my implementation, but without the use of fold.
I like the mutual recursion between common_type and common_type_impl, but really you've just implemented fold, and it would be better to have fold as a separate reusable algorithm. I see that you've isolated the SFINAE-friendliness in your library to the eval_or_default utility. It's an interesting choice, but I think it's why you can't use a fold here, am I right?
I can use a fold if the fold is SFINAE-friendly, yes. But I'm not yet convinced that it has to be. This would imply making all algorithms SFINAE-friendly, or making fold an exception, or adding both SFINAE/non-SFINAE variants of some. None of those sounds appealing.
...unless there's some way to use the same fold for both, giving the user a way to choose. -- Eric Niebler Boost.org http://www.boost.org