I need to have a template struct Lists, whose variadic parameters can only be the types represented by specializations of some certain container template List. Different Lists instances should be able to depend on different (but fixed for one instance) templates List.
That said, I want to produce the code, equivalent to following pseudocode:
template<typename...>
struct Lists;
// pseudocode. Is there a way to do something similar?
template<template<typename...> typename List, typename... Types>
struct Lists<List<Types...>...>{};
int main()
{
Lists<std::pair<int, char>,std::pair<double, char>> lists;
Lists<std::tuple<int, char>,std::tuple<double, char>> lists;
//Lists<std::pair<int, char>,std::tuple<double, char>> lists; // must cause a compilation error
return 0;
}
How can I do that in modern C ?
CodePudding user response:
template <template <typename...> typename, typename>
inline constexpr bool is_specialization_of = false;
template <template <typename...> typename Template, typename... Ts>
inline constexpr bool is_specialization_of<Template, Template<Ts...>> = true;
template <typename...>
struct Lists;
template <template <typename...> typename Template, typename... Ts,
typename... Others>
requires(is_specialization_of<Template, Others> && ...)
struct Lists<Template<Ts...>, Others...> {};
int main() {
Lists<std::pair<int, char>, std::pair<double, char>> lists0; // OK
Lists<std::tuple<int, char>, std::tuple<double, char>> lists1; // OK
/* Lists<std::pair<int, char>,std::tuple<double, char>> lists2; */ // ERROR
}