template <typename... Args> struct type_list; namespace impl { template <template <typename...> class F,class L> struct transform_impl; template <template <typename...> class F,template <typename...> class L,typename... T> struct transform_impl<F,L<T...>> { using type = L<typename F<T>::type...>; }; } template <template <typename...> class F,class L> using transform = typename impl::transform_impl<F,L>::type;
第二种风格是定义元’方法'(使用类型列表结构中的声明).以下是这种风格的变形风格:
template <typename... Args> struct type_list { // ... other 'methods' template<template<class> class Wrapper> using transform = type_list<Wrapper<Args>...>; // ... other 'methods' };
我在第二种风格中看到的优点是您仍然可以使用Args …参数包,因此您不必委托到impl辅助函数.两个可能的缺点是:1)您必须将所有的元函数放在type_list中,而不是将它们放在单独的头文件中,这样就失去了一些模块性,2)“自由”元函数也可以用于元组和任何其他可变模板班开箱.我不知道#2的欲望实际上是多么的普遍,实际上我只是发现使用type_list和元组本身,并且编写元代码来在type_list和元组之间进行转换并不困难.
有什么好的理由强烈地喜欢一个或另一个?也许#2实际上是一个常见的情况?
解决方法
首先,称它是一团糟.模板中的模板需要使用模板关键字.
其次,它要求您的类型列表包括您要在其主体内的类型列表中执行的每个操作.它就像将字符串上的每个操作定义为字符串中的一个方法:如果允许自由功能,可以创建新的操作,甚至可以实现覆盖.
最后,考虑隐藏:: type:
从这些原语开始:
template<class T>struct tag{using type=T;}; template<class Tag>using type_t=typename Tag::type; template<class...Ts>struct types : tag<types<Ts...>>{};
变换或fmap,然后看起来像:
template<template<class...>class Z,class Types> struct fmap; template<template<class...>class Z,class...Ts> struct fmap<Z,types<Ts...>>:types<Z<Ts...>>{}; template<template<class...>class Z,class Types> using fmap_t = type_t<fmap<Z,Types>>;
您可以使用type_t< fmap< Z,类型< int,double>>或gtmap或fmap_t< Z,double>>以获取映射到类型的类型.
template<template<class...>class Z> struct z {template<class...Ts>using apply=Z<Ts...>;}; template<class T>struct tag{using type=T;}; template<class...>struct types{using type=types;}; template<class Tag>using type_t=typename Tag::type;
现在fmap是简单的:
template<template<class...>class Z,class...Ts> constexpr auto fmap( z<Z>,types<Ts...> ) -> types<Z<Ts>...> { return {}; }
其他功能如下:
template<template<class...>class Z,class...Ts> constexpr auto apply( z<Z>,types<Ts...> ) -> type<Z<Ts...>> { return {}; } template<class...Tags> constexpr auto make_list( Tags... ) -> types<type_t<Tags>...> { return {}; } constexpr types<> concat() { return {}; } template<class...T1s,class...T2s> constexpr auto concat(types<T1s...>,types<T2s...>) ->types<T1s...,T2s...>{ return {}; } template<class...T1s,class...T2s,class...Types> constexpr auto concat(types<T1s...>,types<T2s...>,Types...) ->decltype( concat(types<T1s...,T2s...>,Types{}...) ) { return {}; } // must be in the namespace of `types` to allow ADL to work
并使用psuedo类型(标签),而不是直接在顶级的类型.如果您想要使用type_t来提升类型.
我认为这是一个boost :: hana喜欢的方法,但我只是开始看boost :: hana.这里的优点在于,我们将类型捆绑从操作中解耦出来,我们可以访问全部C超载(而不是模板匹配,这可能更脆弱),我们直接推断出类型bundle的内容,而不必做使用和空的主要专业技巧.
消费的所有东西都是一种包装类型的标签<?>或类型<?或z?,所以没有什么是“真实的”.