P<First, Rest...>
, where First
is not a pack, shall be called "nice".
P<Q<R<..<<W<T>>>..>>>
, where T
is "nice", shall be called "cool". And any type that is "nice" is also "cool".
So, let's suppose that we have the "cool" pack
P<Q<R<..<<Z<First, Rest...>>>..>>>
How do we get extract the type First
and std::tuple<Rest...>
?
Here is my implementation for the traits classes is_nice
and is_cool
:
#include <tuple>
#include <type_traits>
template <typename T> struct is_pack : std::false_type {};
template <template <typename...> class P, typename... Ts>
struct is_pack<P<Ts...>> : std::true_type {};
template <typename T> struct is_nice : std::false_type {};
template <template <typename...> class P, typename First, typename... Rest>
struct is_nice<P<First, Rest...>> : std::conditional_t<is_pack<First>::value, std::false_type, std::true_type> {};
template <typename T> struct is_cool : std::conditional_t<is_nice<T>::value, std::true_type, std::false_type> {};
template <template <typename...> class P, typename T>
struct is_cool<P<T>> : std::conditional_t<is_pack<T>::value,
std::conditional_t<is_cool<T>::value, std::true_type, std::false_type>,
std::true_type> {};
// Test
template <typename...> class P;
template <typename...> class Q;
template <typename...> class R;
int main () {
static_assert(is_nice<P<int, bool, char>>::value == true);
static_assert(is_cool<P<int, bool, char>>::value == true);
static_assert(is_cool<P<Q<R<int, bool, char>>>>::value == true);
static_assert(is_nice<P<int>>::value == true);
static_assert(is_cool<P<int>>::value == true);
static_assert(is_cool<P<Q<R<int>>>>::value == true);
}
For those wondering what is my use case for this, I'm trying define foo
as follows:
template <typename T, typename...>
struct foo { using type = T; };
template <template <typename...> class P, typename First, typename... Rest, typename T, typename... Ts>
struct foo<P<First, Rest...>, T, Ts...> {
using type = std::pair<First, T>;
};
template <template <typename...> class P, template <typename...> class Q, typename First, typename... Rest, typename T, typename... Ts>
struct foo<P<Q<First, Rest...>>, T, Ts...> {
using type = std::pair<First, T>;
};
template <template <typename...> class P, template <typename...> class Q, template <typename...> class R, typename First, typename... Rest, typename T, typename... Ts>
struct foo<P<Q<R<First, Rest...>>>, T, Ts...> {
using type = std::pair<First, T>;
};
// etc... for any number of nested templates in this manner.
template <template <typename...> class P, typename First, typename... Rest>
struct foo<P<First, Rest...>> {
using type = std::tuple<Rest...>;
};
template <template <typename...> class P, template <typename...> class Q, typename First, typename... Rest>
struct foo<P<Q<First, Rest...>>> {
using type = std::tuple<Rest...>;
};
template <template <typename...> class P, template <typename...> class Q, template <typename...> class R, typename First, typename... Rest>
struct foo<P<Q<R<First, Rest...>>>> {
using type = std::tuple<Rest...>;
};
// etc... for any number of nested templates in this manner.
This is what I have so far to implement the above in general:
template <typename T, typename...>
struct foo { using type = T; };
template <typename T, typename Void, typename First, typename... Rest>
struct check_cool {
using type = T;
};
template <typename T, typename First, typename... Rest>
struct check_cool<T, std::enable_if_t<is_cool<T>::value>, First, Rest...> {
using type = std::pair<???, First>;
};
template <typename T, typename First, typename... Rest>
struct foo<T, First, Rest...> : check_cool<T, void, First, Rest...> {};
Aucun commentaire:
Enregistrer un commentaire