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>;
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.