如以下示例所示,定义template_pack。给定

template <typename> struct A;
template <typename, typename, typename> struct B;
template <typename, typename> struct C;

然后
template_pack<std::tuple<char, bool, double>, A, B, C>::type

将是
std::tuple<A<char>, B<char, bool, double>, C<char, bool>>

即始终在元组中从左到右读取,以获取足够的类型以适合每个模板。

到目前为止,这是我的解决方案。但这仅适用于最多包含3种类型的模板,并且我看不到如何将其推广到任意数量的类型的模板:
#include <type_traits>
#include <tuple>

template <template <typename...> class Template, typename... Ts> struct use_template;

template <template <typename> class Template, typename A, typename... Rest>
struct use_template<Template, A, Rest...> {
    using type = Template<A>;
};

template <template <typename, typename> class Template, typename A, typename B, typename... Rest>
struct use_template<Template, A, B, Rest...> {
    using type = Template<A,B>;
};

template <template <typename, typename, typename> class Template, typename A, typename B, typename C, typename... Rest>
struct use_template<Template, A, B, C, Rest...> {
    using type = Template<A,B,C>;
};

template <typename Pack, template <typename...> class... Templates> struct template_pack;

template <template <typename...> class P, typename... Ts, template <typename...> class... Templates>
struct template_pack<P<Ts...>, Templates...> {
    using type = P<typename use_template<Templates, Ts...>::type...>;
};

// Testing
template <typename> struct A;
template <typename, typename, typename> struct B;
template <typename, typename> struct C;

int main() {
    static_assert (std::is_same<
        template_pack<std::tuple<char, bool, double>, A, B, C>::type,
        std::tuple<A<char>, B<char, bool, double>, C<char, bool>>
    >::value, "");
}

如何概括以上内容?可能吗

最佳答案

这是“查找最短前缀”。

实用程序:

// pack that is easy to append to
template<class... Ts>
struct pack{
    template<class... T1s>
    using append = pack<Ts..., T1s...>;
};

template<class...> using void_t = void;

这肉:
// find the shortest proper prefix Ts... of [T, Rest...]
// such that A<Ts...> is well-formed, and return it.
template<template<class...> class A, // template we are going to look at
         class AlwaysVoid,           // for void_t
         class Current,              // pack containing the types we are testing next
         class T,                    // next type to add to pack if test fails
         class... Rest>              // remaining types
struct find_viable
    : find_viable<A, AlwaysVoid, typename Current::template append<T>, Rest...> {};

// picked if A<Ts...> is well-formed
template<template<class...> class A, class... Ts, class T, class...Rest>
struct find_viable<A, void_t<A<Ts...>>, pack<Ts...>, T, Rest...> {
    using type = A<Ts...>;
};

// Finds the shortest prefix of Ts... such that A<prefix...> is well formed.
// the extra void at the end is slightly hackish - find_viable only checks
// proper prefixes, so we add an extra dummy type at the end.
template<template<class...> class A, class... Ts>
using find_viable_t = typename find_viable<A, void, pack<>, Ts..., void>::type;

然后使用它:
template <typename Pack, template <typename...> class... Templates> struct template_pack;

template <template <typename...> class P, typename... Ts,
          template <typename...> class... Templates>
struct template_pack<P<Ts...>, Templates...> {
    using type = P<find_viable_t<Templates, Ts...>...>;
};

关于c++ - 通过模板包进行扩展,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37220932/

10-13 08:27
查看更多