【发布时间】:2011-11-24 06:42:39
【问题描述】:
我实际上是想看看是否可以得到一个最小的库来支持我从 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;
};
由于元函数foreach 的实现很简单,我认为zip 也很简单。显然,情况并非如此。
template < typename... >
struct zip;
template < typename... Types0, typename... Types1 >
struct zip < typelist < Types0... >, typelist < Types1... > >
{
typedef typelist < typelist < Types0, Types1 >... > type;
};
如何将此zip 元函数推广到任意数量的类型列表?我们这里需要的似乎是参数包的参数包。我不知道该怎么做。
编辑 1:
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;
};
我认为zip 也可以采用类似的方法...尚未尝试使用zip,但我回家后会这样做。
编辑 2:
这是我最终认为看起来更优雅的东西。这基本上是 Vaughn Cato 方法的一种变体。
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... >
{
};
这会将zip 视为fold 操作。
【问题讨论】:
-
真的是拉链吗?我认为 zip 看起来更像
typelist<pair<Types0, Types1>...>(可以推广到除pair之外的任何元函数)。 -
@LucDanton:你是对的。我已经更正了
zip的实现。typelist是广义的pair元函数。但是如何传递任意数量的参数包呢? -
@GregoryPakosz:如果不用样板也能做到,那就太棒了。
-
zip<typelist<one, three, five>, typelist<two, four, six>>::type是typelist<typelist<one, three, five>, typelist<two, four, six>>。这与其说是zip,不如说是cons,有点,不是真的。我建议的是typelist<typelist<Types0, Types1>...>,它产生typelist<typelist<one, two>, typelist<three, four>, typelist<five, six>>。 -
不应该
apply(=map) 生成带有模板参数<F<T1>, F<T2>, F<TRest>… >的模板,而不是像现在这样的F<T1, T2, TRest…>?
标签: c++ c++11 variadic-templates