一次性使用Boost.MPL定义标签和序列

时间:2014-10-20 19:05:22

标签: c++ boost c++03 boost-mpl

我遇到Boost.MPL的问题,我不知道如何处理它。目前是我的代码 看起来像这样:

struct Definition {
  typedef boost::mpl::int_<5> A;
  typedef boost::mpl::int_<3> B;
  typedef boost::mpl::int_<6> C;
  typedef boost::mpl::int_<1> D;
  // (...)

  typedef boost::mpl::vector<
    A
   ,B
   ,C
   ,D
    // (...)
  > Seq;
};

此处,N中的数字mpl::int_< N >表示任意小数 数。然后一些其他代码计算这些数字的总和 由“key”定义的类型,例如对于Definition::D,总和是5 + 3 + 6 (A + B + C)。这需要在编译时完成。这就是我使用的原因 mpl::vector和一些适当的元编程。

我不喜欢当前的方法,因为它以某种方式违反了DRY规则。

我想知道是否有可能提供这样的结构 定义而不需要在mpl::vector中重复类型名称 Seq类型。换句话说,我可能需要一堆宏 允许我写这样的代码:

struct Definition {
  FIELD(A, 5);
  FIELD(B, 3);
  FIELD(C, 6);
  FIELD(D, 1);
  // (...)
  GEN_SEQ() // only if really needed
};

然后Definition::A仍会引用boost::mpl::int_<5>或 至少允许我以某种方式访问​​boost::mpl::int_<5>,并且 Definition::Seq会给我合适的MPL序列。

这只是我的想象力。代码可能看起来不一样,我是 只是寻找选择。

2 个答案:

答案 0 :(得分:1)

我认为,为了以编程方式执行所有操作,您需要将字段的名称设置为可访问的内容 - 如果您只是将它们命名为AB,... isn&#39真的。您可以尝试使您的序列包含两者:

using namespace boost::mpl; // so I don't have to keep typing it

typedef map<
    pair<char_<'A'>, int_<5>>,
    pair<char_<'B'>, int_<3>>,
    pair<char_<'C'>, int_<6>>,
    ...
> Seq;

这样,总结到'D',你会得到:

template <char C>
struct sum_up_to {
    typedef typename boost::mpl::copy_if<Seq, 
        less_than<C>,
        boost::mpl::back_inserter< boost::mpl::vector<> >
        >::type NewSeq;

    typedef typename boost::mpl::accumulate<NewSeq, 
        boost::mpl::int_<0>,
        addNext>::type type;

    static const int value = type::value;
};

我将less_than<C>addNext的实施方式留给您。但是这样你就可以sum_up_to<'D'>::value == 14

答案 1 :(得分:1)

你见过metamonad吗?它有可变的抽象,就像你想要的那样:

#include <mpllibs/metamonad/eval_multi_let_c.hpp>
#include <mpllibs/metamonad/pair.hpp>
#include <mpllibs/metamonad/syntax.hpp>

#include <boost/mpl/plus.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/assert.hpp>

#include <mpllibs/metamonad/metafunction.hpp>
#include <mpllibs/metamonad/lazy_metafunction.hpp>
#include <mpllibs/metamonad/returns.hpp>
#include <mpllibs/metamonad/name.hpp>

#include <boost/mpl/int.hpp>
#include <boost/mpl/times.hpp>
#include <boost/mpl/divides.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/equal_to.hpp>

int main()
{
    using namespace mpllibs::metamonad::name;
    using boost::mpl::equal_to;
    using boost::mpl::plus;
    using boost::mpl::map;
    using boost::mpl::int_;

    using mpllibs::metamonad::eval_multi_let_c;
    using mpllibs::metamonad::syntax;
    using mpllibs::metamonad::pair;

    // test_evaluation_of_expression
    static_assert(
      equal_to<
        int_<14>,
        eval_multi_let_c<
          map<
              pair<a, syntax<int_<5>> >,
              pair<b, syntax<int_<3>> >,
              pair<c, syntax<int_<6>> >
          >,
          plus<a, b, c> >::type
      >::value, "Yay, maths still work"
    );
}