0

I am trying to write a small meta-program using boost.mpl that matches "named channels" between to audio formats using two channel maps.

The Name is also an integer (enumeration). A simple example of what I am trying to achieve in a runtime might look like:

typedef int Name;
std::map<int, int> map_channels(const std::map<int, Name>& m1, const std::map<Name, int>& m2)
{
    std::map<int, int> result;
    for (std::map<int, Name>::const_iterator it = m1.begin(); it != m1.end(); ++it)
    {
        result[it->first] = m2.find(it->second)->second; // Ignoring errors for example
    }
    return result;
}

int main()
{
    std::map<int, Name> m1;
    m1[0] = 20;
    m1[1] = 22;
    m1[2] = 21;

    std::map<Name, int> m2;
    m2[19] = 1;
    m2[20] = 2;
    m2[21] = 0;
    m2[22] = 3;

    std::map<int, int> m3 = map_channels(m1, m2);
    for (std::map<int, int>::iterator it = m3.begin(); it != m3.end(); ++it)
    {
        std::cerr << it->first << ":" << it->second << std::endl;
    }
    return 0;
}

I am trying to write a compile time version using boost.mpl and so far have something like:

typedef map<
      pair<int_<0>, int_<20> >
    , pair<int_<2>, int_<22> >
    , pair<int_<3>, int_<21> >
> m1;

typedef map<
      pair<int_<19>, int_<1> >
      , pair<int_<20>, int_<2> >
      , pair<int_<21>, int_<0> >
      , pair<int_<22>, int_<3> >
> m2;

What i want to do is create a 3rd map from the other two maps that looks like:

typedef map<
      pair<int_<0>, int_<2> >
      , pair<int_<2>, int_<3> >
      , pair<int_<3>, int_<0> >
> mapping;

I have tried the following ideas:

// TODO : Dont know how to obtain a vector of keys from a mpl map
typedef vector<int_<0>, int_<2>, int_<3> > m1_keys;
//typedef transform<m1, first<_1> >::type m1_keys; // This does not work. I tried a number of ideas and none worked

// Create the composed function that given a key for m1, looks up the value and then uses that value as a lookup to m2
// This is working fine.
typedef at<m2, at<m1, _1> > composed_m1_m2_expr;
typedef lambda<composed_m1_m2_expr>::type composed_m1_m2_lambda;

// TODO : This fold is no good eithre.
typedef iter_fold<m1_keys, map<>, insert<_1, pair<deref<_2>, apply<composed_m1_m2_lambda, _2 > > > >::type mapping;

Note: I am printing out the values for these things like:

struct print_iipair
{
    template <typename data_tpt>
    void operator()(data_tpt p)
    {
        (void)p;
        std::cerr << "k: " << data_tpt::first::value << ", v: " << data_tpt::second::value << std::endl;
        //std::cerr << "value: " << typeid(p).name() << std::endl;
    }
};

struct print_value
{
    template <typename data_tpt>
    void operator()(data_tpt p)
    {
        (void)p;
        std::cerr << "value: " << data_tpt::value << std::endl;
        //std::cerr << "value: " << typeid(p).name() << std::endl;
    }
};
...
for_each<m1_keys,_>(print_value());
for_each<mapping,_>(print_iipair());

My questions are:

1) How would I create a boost::mpl::vector containing the keys of a boost::mpl::map?

2) How would I implement this iter_fold? I think the issue is around the apply and the _2 used, but not sure how to overcome this problem

Thanks.

1 Answers1

2

Well it turns out that a solution is to use mpl::fold instead of mpl::transform as you can't transform a mpl::map as it produces a container of the same type as the source sequence and uses mpl::push_back to construct it which does not work with a map.

My two solutions which seem to work are:

1) How would I create a boost::mpl::vector containing the keys of a boost::mpl::map?

// Get a mpl::vector containing just the keys from the map m1
typedef fold<m1, vector<>, push_back<_1, first<_2> > >::type m1_keys;

2) How would I implement this iter_fold?

// Create a mapping
typedef at<m2, at<m1, _1> > composed_m1_m2_expr;
typedef lambda<composed_m1_m2_expr>::type composed_m1_m2_lambda;
typedef fold<m1_keys, map<>, insert<_1, pair<_2, composed_m1_m2_lambda::apply<_2> > > >::type mapping;