gpt4 book ai didi

c++ - 如何将 std::tuple 类型与 boost::mpl 算法一起使用?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:15:06 29 4
gpt4 key购买 nike

boost::mpl 算法似乎无法在开箱即用的 std::tuple 类型上工作,例如,以下不编译(boost -1.46.0, g++ 快照 2011-02-19):

#include <tuple>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>

namespace mpl=boost::mpl;

typedef mpl::vector<int,float,bool> types;
static_assert(mpl::contains<types, float>::value, "vector contains bool");

typedef std::tuple<int,float,bool> types2;
// the following does not compile:
// error: no class template named ‘apply’ in ‘struct boost::mpl::contains_impl<boost::mpl::non_sequence_tag>’
static_assert(mpl::contains<types2, float>::value, "tuple contains bool");

使 boost::mpl 算法在 std::tuple 上运行的最简单方法是什么?

  • 做 evtl。 boost::fusion 提供此功能(就像它为 boost::tuple 所做的那样)?
  • 如果不是,是否可以轻松地将 boost::tuple 的融合实现转移到 std::tuple
  • 如果两者都不是,我真的必须实现all the intrinsic metafunctions listed in the MPL documentation吗?或者哪些就足够了? (文档只说“许多内在元函数提供了在大多数情况下都可以工作的默认实现”,但不清楚到底是哪些。一些只提供开始和结束的测试并没有带我去任何地方)。

最佳答案

如果你不想将 std::tuple 转换成 mpl 类型,你可以重载调度 boost mpl 使用的标签:

#include <tuple>
#include <boost/mpl/sequence_tag.hpp>
#include <boost/mpl/pop_front_fwd.hpp>
#include <boost/mpl/push_front_fwd.hpp>
#include <boost/mpl/push_back_fwd.hpp>
#include <boost/mpl/front_fwd.hpp>
#include <boost/mpl/empty_fwd.hpp>
#include <boost/mpl/size_fwd.hpp>
#include <boost/mpl/at_fwd.hpp>
#include <boost/mpl/back_fwd.hpp>
#include <boost/mpl/clear_fwd.hpp>
#include <boost/mpl/pop_back_fwd.hpp>
#include <boost/mpl/iterator_tags.hpp>
#include <boost/mpl/next_prior.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/begin_end_fwd.hpp>


namespace boost { namespace mpl {
namespace aux { struct std_tuple; }

template<class ... Args>
struct sequence_tag<std::tuple<Args...> >
{
typedef aux::std_tuple type;
};

template<>
struct front_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_element<0, Tuple>
{
};
};

template<>
struct empty_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::integral_constant<bool, std::tuple_size<Tuple>::value == 0>
{
};
};

template<>
struct pop_front_impl< aux::std_tuple >
{
template< typename Tuple > struct apply;

template< class First, class ... Types > struct apply<std::tuple<First, Types...>>
{
typedef std::tuple<Types...> type;
};
};

template<>
struct push_front_impl< aux::std_tuple >
{
template< typename Tuple, typename T > struct apply;

template< typename T, typename ... Args >
struct apply<std::tuple<Args...>, T>
{
typedef std::tuple<T, Args...> type;
};
};

template<>
struct push_back_impl< aux::std_tuple >
{
template< typename Tuple, typename T > struct apply;

template< typename T, typename ... Args >
struct apply<std::tuple<Args...>, T>
{
typedef std::tuple<Args..., T> type;
};
};


template<>
struct size_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_size<Tuple>
{
};
};

template<>
struct at_impl< aux::std_tuple >
{
template< typename Tuple, typename N > struct apply
: std::tuple_element<N::value, Tuple>
{
};
};

template<>
struct back_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
: std::tuple_element<std::tuple_size<Tuple>::value - 1, Tuple>
{
};
};

template<>
struct clear_impl< aux::std_tuple >
{
template< typename Tuple > struct apply
{
typedef std::tuple<> type;
};
};

template<>
struct pop_back_impl< aux::std_tuple >
{
template<int ...> struct tuple_seq {};
template<int N, int ...S> struct tuple_gens : tuple_gens<N-1, N-1, S...> {};
template<int ...S> struct tuple_gens<0, S...>{ typedef tuple_seq<S...> type; };

template < class Tuple, class Index> struct apply_impl;
template < class Tuple, int ... S> struct apply_impl<Tuple, tuple_seq<S...>>
{
typedef std::tuple<typename std::tuple_element<S, Tuple>::type...> type;
};

template< typename Tuple > struct apply : apply_impl<Tuple, typename tuple_gens<std::tuple_size<Tuple>::value - 1>::type> { };
};

template< class ... Args >
struct tuple_iter;

template< class ... Args >
struct tuple_iter<std::tuple<Args...>>
{
typedef aux::std_tuple tag;
typedef forward_iterator_tag category;
};

template<>
struct begin_impl< aux::std_tuple >
{
template< class Tuple > struct apply
{
typedef tuple_iter<Tuple> type;
};
};

template<>
struct end_impl< aux::std_tuple >
{
template< typename > struct apply
{
typedef tuple_iter<std::tuple<>> type;
};
};

template< typename First, class ... Args >
struct deref< tuple_iter<std::tuple<First, Args...> > >
{
typedef First type;
};

template< typename First, class ... Args >
struct next< tuple_iter<std::tuple<First, Args...>> >
{
typedef tuple_iter< std::tuple<Args...> > type;
};

} }

和相关的测试:

#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/pop_back.hpp>
#include <boost/mpl/contains.hpp>


#include <boost/mpl/aux_/test.hpp>
MPL_TEST_CASE()
{
typedef std::tuple<int, char, bool> Tuple;
MPL_ASSERT((is_same<front<Tuple>::type, int>));
MPL_ASSERT_RELATION( size<Tuple>::type::value, ==, 3 );
MPL_ASSERT(( is_same< pop_front<Tuple>::type, std::tuple<char, bool> > ));
MPL_ASSERT(( is_same< push_front<Tuple, unsigned>::type, std::tuple<unsigned, int, char, bool> > ));
MPL_ASSERT(( is_same< push_back<Tuple, unsigned>::type, std::tuple<int, char, bool, unsigned> > ));
MPL_ASSERT_RELATION( empty<Tuple>::type::value, ==, false );
MPL_ASSERT(( is_same< at_c<Tuple, 0>::type, int > ));
MPL_ASSERT(( is_same< at_c<Tuple, 1>::type, char > ));
MPL_ASSERT(( is_same< back<Tuple>::type, bool > ));
MPL_ASSERT(( is_same< clear<Tuple>::type, std::tuple<> > ));
MPL_ASSERT(( is_same< pop_back<Tuple>::type, std::tuple<int, char> > ));
MPL_ASSERT(( contains<Tuple, int> ));
MPL_ASSERT(( contains<Tuple, char> ));
MPL_ASSERT(( contains<Tuple, bool> ));
MPL_ASSERT_NOT(( contains<Tuple, unsigned> ));

}

我用 gcc 4.7.2 和 clang 3.2 测试了这个。它应该包含您在 mpl 中使用任何东西所需的一切(实际上比它需要的多一点)。您可以将元组视为 mpl::list(前向迭代器编译类型)。所以,为了让它发挥得更好,你应该实现 boost::mpl::list 的功能。快速查看 boost/mpl/list/aux_ 目录:begin_end.hpp empty.hpp iterator.hpp pop_front.hpp push_back.hpp size.hppclear.hpp front.hpp push_front.hpp tag.hpp是需要执行的相关文件。

关于c++ - 如何将 std::tuple 类型与 boost::mpl 算法一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5099429/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com