Boost logo

Boost :

Subject: Re: [boost] "Simple C++11 metaprogramming"
From: Peter Dimov (lists_at_[hidden])
Date: 2015-06-05 09:23:13


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.


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