在c ++ 11中实现元函数zip [英] Implementing meta-function zip in c++11
问题描述
我实际上想看看是否可以得到一个最小的库,支持从boost :: fusion使用的很少的操作。
这是我有到目前为止...
typename ...类型>
struct typelist
{
};
template<模板typename ...>类F,类型名... Args>
struct apply
{
typedef typename F< Args ...> :: type type;
};
template<类型名称, typename ...> class>
struct foreach;
template< typename ... Types,template< typename Arg>类F>
struct foreach<类型列表类型...>,F>
{
typedef typelist<类型名F,Types> :: type ...>类型;
};
由于元函数 foreach
琐碎,我认为 zip
也很容易。显然不是这样的。
template< typename ...>
struct zip;
template< typename ... Types0,typename ... Types1>
struct zip<类型列表Types0 ...>,typelist< Types1 ...> >
{
typedef typelist<类型列表Types0,Types1> ...>类型;
};
如何概括 zip
函数到任意数量的类型列表?我们需要的是一个参数包的参数包。
的实施
std :: size_t ... Nn>
struct is_equal;
template< std :: size_t N0,std :: size_t N1,std :: size_t ... Nn>
struct is_equal< N0,N1,Nn ...>
:and_<
typename is_equal< N0,N1> :: type
,typename is_equal< N1,Nn ...> :: type
> :: type
{
};
template< std :: size_t M,std :: size_t N>
struct is_equal< M,N> :std :: false_type
{
typedef std :: false_type type;
};
template< std :: size_t N>
struct is_equal< N,N> :std :: true_type
{
typedef std :: true_type type;
};
可以采用类似的方法 zip
以及我认为...还没有尝试过 zip
,但是当我回家时会这样做。
编辑2:
这是我终于认为看起来更优雅。这基本上是Vaughn Cato的方法的变体。
命名空间impl
{
模板< typename Initial, typename,typename> class F,typename ... Types>
struct foldl;
template< typename Initial, typename,typename> class F,typename First,typename ... Rest>
struct foldl<初始,F,第一,休息...>
{
typedef typename foldl&类型名F < Initial,First> :: type,F,Rest ...> :: type type;
};
template< typename Final,template< typename,typename>类F>
struct foldl<最终,F>
{
typedef最终类型;
};
template< typename Type,typename TypeList>
struct cons;
template< typename类型,类型名称...类型>
struct cons<类型, Types ...> >
{
typedef typelist<类型...,类型>类型;
};
template< typename,typename>
struct zip_accumulator;
template< typename ... Types0,typename ... Types1>
struct zip_accumulator<类型列表Types0 ...>,typelist< Types1 ...> >
{
typedef typelist< typename cons< Types1,Types0> :: type ...>类型;
};
template< typename ... Types0>
struct zip_accumulator< typelist<>,typelist< Types0 ...> >
{
typedef typelist<类型列表Types0> ...>类型;
};
template< typename ...类型列表>
struct zip
{
typedef typename foldl& typelist<>,zip_accumulator,TypeLists ...> :: type type;
};
}
template< typename ...类型列表>
struct zip
{
static_assert(and_< typename is_type_list< TypeLists> ...> :: value,All parameters must be type lists for zip);
static_assert(is_equal< TypeLists :: length ...> :: value,所有参数类型列表的长度必须与zip相同);
typedef typename impl :: zip< TypeLists ...> :: type type;
};
template< typename ...类型列表>
struct zip<类型列表类型列表...> > :zip<类型列表...>
{
};
这将 zip
视为<$ c这是我发现的最短的实现:
p>
模板< typename ...> struct typelist {};
template< typename A,typename B> struct prepend;
template< typename A,typename B> struct joincols;
template< typename ...> struct zip;
template< typename A,typename ... B>
struct prepend< A,typelist< B ...> > {
typedef typelist< A,B ...>类型;
};
模板<>
struct joincols< typelist<>,typelist<> > {
typedef typelist<>类型;
};
template< typename A,typename ... B>
struct joincols< typelist< A,B ...>,typelist<> > {
typedef typename
prepend<
typelist< A>,
typename joincols< typelist< B ...>,typelist< > :: type
> :: type type;
};
template< typename A,typename ... B,typename C,typename ... D>
struct joincols< typelist< A,B ...>,typelist< C,D ...> > {
typedef typename
prepend<
typename prepend< A,C> :: type,
typename joincols< typelist< B ...>,typelist< D ...> > :: type
> :: type type;
};
模板<>
struct zip<> {
typedef typelist<>类型;
};
template< typename A,typename ... B>
struct zip< A,B ...> {
typedef typename joincols< A,typename zip< B ...> :: type> :: type type;
};
I am actually trying to see if I can get a minimal library that supports the very few operations I use from boost::fusion.
Here is what I have so far...
template < typename... Types >
struct typelist
{
};
template < template < typename... > class F, typename... Args >
struct apply
{
typedef typename F < Args... >::type type;
};
template < typename, template < typename... > class >
struct foreach;
template < typename... Types, template < typename Arg > class F >
struct foreach < typelist < Types... >, F >
{
typedef typelist < typename apply < F, Types >::type... > type;
};
Since the meta-function foreach
implementation is trivial, I thought zip
would be easy too. Apparently, this is not the case.
template < typename... >
struct zip;
template < typename... Types0, typename... Types1 >
struct zip < typelist < Types0... >, typelist < Types1... > >
{
typedef typelist < typelist < Types0, Types1 >... > type;
};
How can I generalize this zip
meta-function to arbitrary number of typelists? What we need here seems to be a parameter pack of parameter packs. I am not sure how to do that.
Edit 1:
Implementation of is_equal
...
template < std::size_t... Nn >
struct is_equal;
template < std::size_t N0, std::size_t N1, std::size_t... Nn >
struct is_equal < N0, N1, Nn... >
: and_ <
typename is_equal < N0, N1 >::type
, typename is_equal < N1, Nn... >::type
>::type
{
};
template < std::size_t M, std::size_t N >
struct is_equal < M, N > : std::false_type
{
typedef std::false_type type;
};
template < std::size_t N >
struct is_equal < N, N > : std::true_type
{
typedef std::true_type type;
};
A similar approach can be taken to zip
as well I think... haven't tried with zip
yet, but will do so when I get back home.
Edit 2:
Here is what I finally thought looked more elegant. This is basically a variation of Vaughn Cato's approach.
namespace impl
{
template < typename Initial, template < typename, typename > class F, typename... Types >
struct foldl;
template < typename Initial, template < typename, typename > class F, typename First, typename... Rest >
struct foldl < Initial, F, First, Rest... >
{
typedef typename foldl < typename F < Initial, First >::type, F, Rest... >::type type;
};
template < typename Final, template < typename, typename > class F >
struct foldl < Final, F >
{
typedef Final type;
};
template < typename Type, typename TypeList >
struct cons;
template < typename Type, typename... Types >
struct cons < Type, typelist < Types... > >
{
typedef typelist < Types..., Type > type;
};
template < typename, typename >
struct zip_accumulator;
template < typename... Types0, typename... Types1 >
struct zip_accumulator < typelist < Types0... >, typelist < Types1... > >
{
typedef typelist < typename cons < Types1, Types0 >::type... > type;
};
template < typename... Types0 >
struct zip_accumulator < typelist <>, typelist < Types0... > >
{
typedef typelist < typelist < Types0 >... > type;
};
template < typename... TypeLists >
struct zip
{
typedef typename foldl < typelist <>, zip_accumulator, TypeLists... >::type type;
};
}
template < typename... TypeLists >
struct zip
{
static_assert(and_ < typename is_type_list < TypeLists >... >::value, "All parameters must be type lists for zip");
static_assert(is_equal < TypeLists::length... >::value, "Length of all parameter type lists must be same for zip");
typedef typename impl::zip < TypeLists... >::type type;
};
template < typename... TypeLists >
struct zip < typelist < TypeLists... > > : zip < TypeLists... >
{
};
This treats zip
as a fold
operation.
This is the shortest implementation I've discovered:
template <typename...> struct typelist { };
template <typename A,typename B> struct prepend;
template <typename A,typename B> struct joincols;
template <typename...> struct zip;
template <typename A,typename... B>
struct prepend<A,typelist<B...> > {
typedef typelist<A,B...> type;
};
template <>
struct joincols<typelist<>,typelist<> > {
typedef typelist<> type;
};
template <typename A,typename... B>
struct joincols<typelist<A,B...>,typelist<> > {
typedef typename
prepend<
typelist<A>,
typename joincols<typelist<B...>,typelist<> >::type
>::type type;
};
template <typename A,typename... B,typename C,typename... D>
struct joincols<typelist<A,B...>,typelist<C,D...> > {
typedef typename
prepend<
typename prepend<A,C>::type,
typename joincols<typelist<B...>,typelist<D...> >::type
>::type type;
};
template <>
struct zip<> {
typedef typelist<> type;
};
template <typename A,typename... B>
struct zip<A,B...> {
typedef typename joincols<A,typename zip<B...>::type>::type type;
};
这篇关于在c ++ 11中实现元函数zip的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!