Skip to content

boost::mp11::mp_transform is not SFINAE friendly on transform error #101

@wanghan02

Description

@wanghan02

Example could be found below or on godbolt. boost::mp11::mp_transform is not SFINAE friendly on transform error. It is SFINAE friendly on size mismatch though. It would be very helpful in constraints if it is SFINAE friendly.

template<template<typename...> typename F, typename... List>
concept has_boost_mp_transform = requires { typename boost::mp11::mp_transform<F, List...>; };

static_assert(!has_boost_mp_transform<std::remove_cvref_t, boost::mp11::mp_list<int&, double const>, std::tuple<short, int const&>>); // invalid transform. Does not compile.
static_assert(!has_boost_mp_transform<std::common_type_t, boost::mp11::mp_list<char*, float>, boost::mp11::mp_list<int, double>>); // invalid transform result. Does not compile.
static_assert(!has_boost_mp_transform<std::common_type_t, boost::mp11::mp_list<short, float>, boost::mp11::mp_list<int, double, char>>); // size mismatch. Compiles.

An example implementation for c++20 could be found below or on godbolt.

namespace no_adl {
    template<template<typename...> typename F, typename List0, typename... List>
    struct mp_transform_impl {};

    template<template<typename...> typename F, template<typename...> typename TList0, typename... List>
    struct mp_transform_impl<F, TList0<>, List...> {
        using type = TList0<>;
    };

    template<template<typename...> typename F, template<typename...> typename TList0, typename T0, typename... T, typename... List> requires
        requires { typename F<T0, boost::mp11::mp_front<List>...>; } &&
        requires { typename mp_transform_impl<F, TList0<T...>, boost::mp11::mp_pop_front<List>...>::type; }
    struct mp_transform_impl<F, TList0<T0, T...>, List...> {
        using type = boost::mp11::mp_append<
            TList0<F<T0, boost::mp11::mp_front<List>...>>,
            typename mp_transform_impl<F, TList0<T...>, boost::mp11::mp_pop_front<List>...>::type
        >;
    };

    template<template<typename...> typename F, typename... List>
        requires boost::mp11::mp_same<boost::mp11::mp_size<List>...>::value && (0<sizeof...(List))
    struct mp_transform: mp_transform_impl<F, List...> {};
}

template<template<typename...> typename F, typename... List>
using mp_transform = typename no_adl::mp_transform<F, List...>::type;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions