C++ 在c+中实现元函数zip+;11

C++ 在c+中实现元函数zip+;11,c++,c++11,variadic-templates,C++,C++11,Variadic Templates,我实际上是想看看我是否能得到一个最小的库来支持我从boost::fusion中使用的极少数操作 这是我到目前为止所拥有的 template < typename... Types > struct typelist { }; template < template < typename... > class F, typename... Args > struct apply { typedef typename F < Args... >:

我实际上是想看看我是否能得到一个最小的库来支持我从boost::fusion中使用的极少数操作

这是我到目前为止所拥有的

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; 
};
如何将此
zip
元函数推广到任意数量的类型列表?这里我们需要的似乎是参数包中的参数包。我不知道该怎么做

编辑1:

的实现相当于

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;
};

这将
zip
视为一个
fold
操作。

似乎可以使用成熟的列表(即head、tail和cons操作)和递归。使用GCC4.7的快照进行测试,所有的
std
内容都来自

struct nil{};
模板
结构是_nil:std::是_same{};
模板
结构和类型:std::true\u类型{};
模板
结构和_
:std::积分常数<
布尔
,First::value&&和_u::value
> {};
模板
结构不是_
:std::积分_常数{};
模板
结构类型表;
模板
结构类型表{
typedef第一个头;
typedef类型列表尾部;
};
模板
结构类型表{
最后一个头;
无尾型;
};
模板
结构缺陷;
模板
结构控制{
typedef类型列表类型;
};
//解决方法:
//抱歉,未实现:无法将“…”扩展到固定长度的参数列表中
模板
结构gcc_变通方法{
typedef模板类型;
};
名称空间详细信息{
模板
结构拉链;
模板
结构拉链<
typename std::enable_if::type
,列出。。。
> {
typedef类型列表类型;
};
模板
结构拉链<
typename std::enable_if::type
,列出。。。
> {
typedef typename cons<
类型表
,typename gcc_变通方法::type::type
>::类型类型;
};
}//细节
模板
结构zip:detail::zip{};
您可能希望将错误检查添加到所有这些中(我认为无效的实例化目前只是作为不完整的类型保留)。坦白地说,考虑到我花了很多时间才弄明白这一点,我建议坚持使用Boost.MPL。像懒惰评估(我不需要用它来做SFINAE的事情)这样的事情是一种恩惠,我不喜欢重新发明它们。再加上它的C++11使您能够收获两全其美的一天



我忘了提到Boost.MPL还有泛型的优点。它可以在满足其序列概念的任何类型上工作(也可以非侵入性地修改先前存在的类型),而强制使用
类型列表

这是我发现的最短实现:

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;
};
模板结构类型列表{};
模板结构前置;
模板结构joincols;
模板结构zip;
模板
结构前置{
typedef类型列表类型;
};
模板
结构joincols{
typedef类型列表类型;
};
模板
结构joincols{
typedef typename
预编<
类型列表,
typename joincols::type
>::类型类型;
};
模板
结构joincols{
typedef typename
预编<
typename prepend::type,
typename joincols::type
>::类型类型;
};
模板
结构拉链{
typedef类型列表类型;
};
模板
结构拉链{
typedef typename joincols::type type;
};

那真的是拉链吗?我原以为zip看起来更像是
类型列表
(可以广义为接受除
)以外的任何元函数)。@LucDanton:你说得对。我已经更正了
zip
实现<代码>类型列表是广义的
元函数。但是我如何传递任意数量的参数包呢?@GregoryPakosz:如果这可以在没有锅炉板的情况下完成,那将是一件非常糟糕的事情。
zip::type
typelist
。这与其说是一个邮政编码,不如说是一个cons,有点,不是真的。我建议的是
typelist
,它产生
typelist
。不应该
apply
(=
map
)产生一个带有模板参数的模板,而不是现在的
F
?将
typelist
类型实现为cons列表可以完成任务。我想知道它是否可以不借助于此来完成。@zrb您可以执行
template struct foo{…
但这只会匹配具有相同元素的列表。答案被大大低估了,这+1用于避免
enable_if
gcc_解决方案
,并完全依赖模板模式匹配。我想我看到了一些模式从中涌现出来。我正在添加我使用的
is_equal
元函数的实现d使用
zip
,以确保其所有参数
typelist
具有相同的长度。请您解释一下什么是zip元函数?这也与zip元函数有关吗?。Thanks@Mr.Anubis:这里有一个很好的答案:
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... >
{
};
struct nil {};

template<typename T>
struct is_nil: std::is_same<T, nil> {};

template<typename... T>
struct and_: std::true_type {};

template<typename First, typename... Rest>
struct and_<First, Rest...>
: std::integral_constant<
    bool
    , First::value && and_<Rest...>::value
> {};

template<typename T>
struct not_
: std::integral_constant<bool, !T::value> {};

template<typename... T>
struct typelist;

template<typename First, typename Second, typename... Rest>
struct typelist<First, Second, Rest...> {
    typedef First head;
    typedef typelist<Second, Rest...> tail;
};

template<typename Last>
struct typelist<Last> {
    typedef Last head;
    typedef nil tail;
};

template<typename T, typename List>
struct cons;

template<typename T, typename... Ts>
struct cons<T, typelist<Ts...>> {
    typedef typelist<T, Ts...> type;
};

// workaround for:
// sorry, unimplemented: cannot expand '...' into a fixed-length argument list
template<template<typename...> class Template, typename... T>
struct gcc_workaround {
    typedef Template<T...> type;
};

namespace detail {

template<typename Sfinae, typename... Lists>
struct zip;

template<typename... Lists>
struct zip<
    typename std::enable_if<and_<is_nil<typename Lists::tail>...>::value>::type
    , Lists...
> {
    typedef typelist<typelist<typename Lists::head...>> type;
};

template<typename... Lists>
struct zip<
    typename std::enable_if<and_<not_<is_nil<typename Lists::tail>>...>::value>::type
    , Lists...
> {
    typedef typename cons<
        typelist<typename Lists::head...>
        , typename gcc_workaround<zip, void, typename Lists::tail...>::type::type
    >::type type;
};

} // detail

template<typename... Lists>
struct zip: detail::zip<void, Lists...> {};
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;
};