在c ++ 11中实现元函数zip [英] Implementing meta-function zip in c++11

查看:100
本文介绍了在c ++ 11中实现元函数zip的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上想看看是否可以得到一个最小的库,支持从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 函数到任意数量的类型列表?我们需要的是一个参数包的参数包。



的实施

is_equal ...

  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这是我发现的最短的实现:

$ b

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆