介绍
我的答案试图成为 C++11 用户的首选。
Joel Falcou 的回答非常适合旧标准,但 C++11 的参数包通常会使 boost 类型序列过时。此外,我认为在这种情况下,捎带模板比使用boost::lambda
. 实际上,我的解决方案根本不使用包含,除了笛卡尔产品模板,我将从这里获取, 因为它不在标准库中。
使用当前最新的功能(自 C++11 起)允许编写以下解决方案:
- 尺度更好。
- 更短
- 更具可读性,因为解决方案将关注点分开。
不同的模板解释:
expand_pack
执行其参数。这允许使用省略号重复运行时代码。示例:expand_pack(new T{}...)
。有谁知道这个成语的名字吗?
wrap_template_as_type
捎带一个模板,以便可以在需要类型的地方使用它。也许这个成语被称为模板重新绑定或后期模板绑定。我不知道所以我在这里发布了这个问题。例子:wrap_template_as_type<map>
反之亦然wrapper::unwrapp<int, string>
type_list
一个没有数据、铃铛和智慧的元组。
template_list
一个模板,它接受一个模板列表并返回一个 type_list,其中原始模板搭载在包装器中。
make_host_type
转换A, B, C, D
成A<B<C<D>>>
all_hosts
获取主机类型的元组,并为输入元组中的每个元素获取一个主机。
完整示例
注意#include http://...
必须替换为链接内容
请注意,我认为MSVC 不理解PRETTY_FUNCTION但FUUNCDNAME
#include <iostream>
#include <typeinfo>
#include https://stackoverflow.com/a/19611856/2712726
template<typename... Ts> void expand_pack (Ts... t) {}
template <template<typename...> class T>
struct wrapp_template_as_type {
template <typename... Us> using unwrapp = T <Us...>;
};
template<typename... T> struct type_list {};
template <template<typename...> class... Ts>
struct template_list {
using type = type_list< wrapp_template_as_type<Ts>... >;
};
struct TraitA{}; struct TraitB{}; struct TraitC{}; struct TraitD{}; struct TraitE{}; struct TraitF{};
template<typename Trait> struct WhateverA{};
template<typename Trait> struct WhateverB{};
template<typename Whatever> struct FunctionalityA{};
template<typename Whatever> struct FunctionalityB{};
template<typename Whatever> struct FunctionalityC{};
template<typename Whatever> struct FunctionalityD{};
template<typename Func> struct FuncUserA{};
template<typename Func> struct FuncUserB{};
template<typename Func> struct FuncUserC{};
template<typename FuncUser> struct Host { Host() {std::cout << __PRETTY_FUNCTION__ << std::endl;}};
template<typename T> struct make_host_type;
template<template<typename...> class List, typename T, typename... Ts>
struct make_host_type < List<T, Ts...> > {
using type = typename T::template unwrapp < typename make_host_type< List<Ts...> >::type >;
};
template<template<typename...> class List, typename T>
struct make_host_type < List<T> > {
using type = T;
};
template <typename T> struct all_hosts;
template <template<typename...> class Hosts, typename... Ts>
struct all_hosts <Hosts<Ts...> > {
static void create () {
expand_pack (new typename make_host_type<Ts>::type{}...);
}
};
int main () {
using a = type_list < TraitA, TraitB, TraitC, TraitD, TraitE, TraitF >;
using b = typename template_list < WhateverA, WhateverB>::type;
using c = typename template_list < FunctionalityA, FunctionalityB, FunctionalityC, FunctionalityD >::type;
using d = typename template_list < FuncUserA, FuncUserB, FuncUserC >::type;
using e = typename template_list < Host >::type;
using p = typename product<type_list, e, d, c, b, a>::type; // create a type_list of all possible Host types.
all_hosts<p>::create(); // calls constructor for each Host type
}
输出为:(如果您使用 MSVC,请将PRETTY_FUNCTION替换为其他内容)
Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityD<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityD<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityD<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityC<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityC<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityC<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserC<FunctionalityB<WhateverB<TraitF> > >]
Host<FuncUser>::Host() [with FuncUser = FuncUserB<FunctionalityB<WhateverB<TraitF> > >]
...
Host<FuncUser>::Host() [with FuncUser = FuncUserA<FunctionalityA<WhateverA<TraitA> > >]