我有以下模板化的类结构
struct TraitA{};
struct TraitB{};
template<typename trait>
struct FunctionalityA{};
template<typename trait>
struct FunctionalityB{};
template<typename Func>
struct FuncUserA{};
template<typename Func>
struct FuncUserB{};
template<typename fuser>
struct Host{};
Host类现在可以使用以下类型。
typedef Host<FuncUserA<FunctionalityA<TraitA> > > Host1_t;
typedef Host<FuncUserA<FunctionalityA<TraitB> > > Host2_t;
typedef Host<FuncUserA<FunctionalityB<TraitA> > > Host3_t;
typedef Host<FuncUserA<FunctionalityB<TraitB> > > Host4_t;
typedef Host<FuncUserB<FunctionalityA<TraitA> > > Host5_t;
typedef Host<FuncUserB<FunctionalityA<TraitB> > > Host6_t;
typedef Host<FuncUserB<FunctionalityB<TraitA> > > Host7_t;
typedef Host<FuncUserB<FunctionalityB<TraitB> > > Host8_t;
有没有办法用boost :: mpl创建一个类型列表?目前我甚至没有想法从哪里开始。 我的目标是拥有这样的功能:
template<class T>
T* getHost()
{
typedef boost::mpl::find<HostVector, T>::type MplIter;
return new MplIter;
}
这可以用boost :: mpl吗?
答案 0 :(得分:5)
好的,这是一些实现。它是ad-hoc,显然可以将它抽象为采用一系列lambda函数序列,但我更喜欢保持这一点。评论和测试在里面:
#include <iostream>
////////////////////////////////////////////////////////////////////////////////
// Base types to permute around - added soem display for tests purpose
////////////////////////////////////////////////////////////////////////////////
struct TraitA { TraitA() { std::cout << "TA"; } };
struct TraitB { TraitB() { std::cout << "TB"; } };
template<typename Trait>
struct FunctionalityA
{
FunctionalityA() { std::cout << "FunctionalityA<"; Trait(); std::cout << ">";}
};
template<typename Trait>
struct FunctionalityB
{
FunctionalityB() { std::cout << "FunctionalityB<"; Trait(); std::cout << ">";}
};
template<typename Func>
struct FuncUserA
{
FuncUserA() { std::cout << "FuncUserA<"; Func(); std::cout << ">";}
};
template<typename Func>
struct FuncUserB
{
FuncUserB() { std::cout << "FuncUserB<"; Func(); std::cout << ">";}
};
template<typename Fuser> struct Host
{
Host() { std::cout << "Host<"; Fuser(); std::cout << ">\n";}
};
////////////////////////////////////////////////////////////////////////////////
// Step 1 : Make static list of potential options
//
// These lists has to be updated as new Trait, FuncUser and Functionality are
// made.
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>
typedef boost::mpl::vector< TraitA, TraitB > traits_list;
typedef boost::mpl::vector< FunctionalityA<boost::mpl::_>
, FunctionalityB<boost::mpl::_>
> functionalities_list;
typedef boost::mpl::vector< FuncUserA<boost::mpl::_>
, FuncUserB<boost::mpl::_>
> fusers_list;
////////////////////////////////////////////////////////////////////////////////
// Step 1 : Build the types
//
// We want every combination of Trait and Functionality. This is basically a
// cartesian product of traits_list and functionalities_list which is done
// usign nested fold
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/fold.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/back_inserter.hpp>
template<typename Fusers, typename Functionalities, typename Traits>
struct build_combo
{
//////////////////////////////////////////////////////////////////////////////
// Inner fold loop iterating over the traits
//////////////////////////////////////////////////////////////////////////////
template<typename FuserFunc>
struct traits_loop
{
template<typename T>
struct fuse : boost::mpl::apply<FuserFunc,T> {};
typedef typename
boost::mpl::fold< Traits
, boost::mpl::vector<>
, boost::mpl::push_back < boost::mpl::_1
, fuse<boost::mpl::_2>
>
>::type type;
};
//////////////////////////////////////////////////////////////////////////////
// Inner fold loop iterating over the functionnality/traits
//////////////////////////////////////////////////////////////////////////////
template<typename Fuser>
struct func_traits_loop
{
template<typename T>
struct fuse : boost::mpl::apply<Fuser,T> {};
typedef typename
boost::mpl::fold< Functionalities
, boost::mpl::vector<>
, boost::mpl::copy< traits_loop< fuse<boost::mpl::_2> >
, boost::mpl::back_inserter<boost::mpl::_1>
>
>::type type;
};
//////////////////////////////////////////////////////////////////////////////
// fold loop iterating over the Fuser x {Functionality,Traits}
// For each Fuser, copy its vector of applications to the others
//////////////////////////////////////////////////////////////////////////////
typedef typename
boost::mpl::fold< Fusers
, boost::mpl::vector<>
, boost::mpl::copy< func_traits_loop<boost::mpl::_2>
, boost::mpl::back_inserter<boost::mpl::_1>
>
>::type type;
};
////////////////////////////////////////////////////////////////////////////////
// Now the get_host meta-function
////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/at.hpp>
template<int N>
struct get_host
{
typedef build_combo < fusers_list
, functionalities_list
, traits_list
>::type types;
typedef typename boost::mpl::at_c<types,N>::type hosted;
typedef Host<hosted> type;
};
////////////////////////////////////////////////////////////////////////////////
// Some tests
////////////////////////////////////////////////////////////////////////////////
int main()
{
get_host<1>::type x1;
get_host<2>::type x2;
get_host<3>::type x3;
get_host<4>::type x4;
get_host<5>::type x5;
get_host<6>::type x6;
get_host<7>::type x7;
}
预期输出应为:
Host<FuncUserA<FunctionalityA<TB>>>
Host<FuncUserA<FunctionalityB<TA>>>
Host<FuncUserA<FunctionalityB<TB>>>
Host<FuncUserB<FunctionalityA<TA>>>
Host<FuncUserB<FunctionalityA<TB>>>
Host<FuncUserB<FunctionalityB<TA>>>
Host<FuncUserB<FunctionalityB<TB>>>
答案 1 :(得分:3)
我的回答试图成为C ++ 11用户的首选。
Joel Falcou的答案很适合旧标准但C ++ 11
参数包通常会使升级类型序列过时。此外,我认为备用模板在这种情况下比使用boost::lambda
更好。
实际上我的解决方案除了笛卡尔产品模板之外根本不使用任何包含,我将从here获取,因为它不在标准库中。
使用当前最新的功能(从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 但 FUNCDNAME 我认为
#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> > >]