我实际上是在尝试查看是否可以使用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
操作。
答案 0 :(得分:6)
这是我发现的最短的实现:
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;
};
答案 1 :(得分:3)
似乎可以使用完全成熟的列表(这意味着头部,尾部和缺点操作)和递归。使用GCC 4.7的快照进行测试,所有std
内容均来自<type_traits>
:
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...> {};
您可能希望将错误检查添加到所有这些(我正在考虑当前简单地保留为不完整类型的无效实例化)。坦率地说,我花了很多时间来弄明白这一点,我建议坚持使用Boost.MPL。像懒惰的评价(我不需要做SFINAE的东西)这样的事情是一个福音,我不喜欢重新发明它们。再加上C ++ 11的那一天,你可以获得两全其美的效果。
我忘了提到Boost.MPL也具有通用性的优点。它可以在满足其序列概念之一的任何类型上工作(它也可以非侵入性地适应预先存在的类型),而你强制使用typelist
。