2014-10-20 17 views
0

我有一個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; 
}; 

這裏,Nmpl::int_<N>表示一些任意的十進制 數目。然後一些其他代碼計算這些數字的總和,直到由「鍵」定義的類型,例如 。對於Definition::D,總和是5 + 3 + 6 (A + B + C)。這需要在編譯時完成。這就是爲什麼我使用 mpl::vector和一些適當的元編程。

我不喜歡目前的做法,因爲它在某種程度上違反了DRY規則。

我想知道它是否能夠提供這樣的結構 定義,而不需要重複類型名稱在mpl::vectorSeq類型。換句話說,我可能需要一幫宏,這 會允許我這樣寫代碼:

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序列。

這是我的想象。代碼可能看起來不一樣,我只是尋找選擇 。

回答

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" 
    ); 
} 
1

我認爲爲了以編程方式完成所有工作,您需要具有可訪問的字段名稱 - 如果您只是將它們命名爲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<C>實施和addNext給你。但這樣你可以只有。