I have a problem with Boost.MPL and I'm not sure how to approach it. Currently my code looks like this:
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;
};
Here, the number N
in mpl::int_< N >
denotes some arbitrary decimal
number. Then some other code calculates the sum of these numbers up to
the type defined by "key", e.g. for Definition::D
, the sum is 5 + 3 + 6
(A + B + C). This needs to be done at compile-time. That's why I use
mpl::vector
and some appropriate meta-programming.
I don't like the current approach since it somehow violates the DRY rule.
I'm wondering whether it would be possible to provide such struct
definition without the need to repeat type names in the mpl::vector
for
Seq
type. In other words, I'd probably need a bunch of macros which
would allow me to write code like this:
struct Definition {
FIELD(A, 5);
FIELD(B, 3);
FIELD(C, 6);
FIELD(D, 1);
// (...)
GEN_SEQ() // only if really needed
};
And then Definition::A
would still refer to boost::mpl::int_<5>
, or
would at least allow me to access the boost::mpl::int_<5>
somehow, and
Definition::Seq
would give me the appropriate MPL sequence.
Of couse this is just my imagination. The code might look different, I'm just looking for options.
Have you seen metamonad? It has variable abstractions just like you seem to want:
#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"
);
}