【问题标题】:Defining tags and sequences with Boost.MPL in one shot使用 Boost.MPL 一次性定义标签和序列
【发布时间】:2014-10-20 19:05:22
【问题描述】:

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

这里,mpl::int_&lt; N &gt; 中的数字 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_&lt;5&gt;,或者 至少可以让我以某种方式访问​​boost::mpl::int_&lt;5&gt;,并且 Definition::Seq 会给我适当的 MPL 序列。

当然,这只是我的想象。代码可能看起来不同,我是 只是在寻找选择。

【问题讨论】:

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


    【解决方案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"
        );
    }
    

    【讨论】:

      【解决方案2】:

      我认为,为了以编程方式完成所有操作,您需要将字段的名称设置为可访问的名称——如果您只是将它们命名为 AB,... 并不是真的。您可以尝试让您的序列包含两者:

      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&lt;C&gt;addNext 的实施留给你。但是这样你就可以拥有sum_up_to&lt;'D'&gt;::value == 14

      【讨论】:

        猜你喜欢
        • 2012-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-04
        • 2015-12-08
        • 2020-05-11
        • 1970-01-01
        • 2011-07-10
        相关资源
        最近更新 更多