Boost logo

Boost :

Subject: Re: [boost] "Simple C++11 metaprogramming"
From: Eric Niebler (eniebler_at_[hidden])
Date: 2015-06-05 11:28:06


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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk