What's the idiomatic way to traverse a boost::mpl::list?

时光毁灭记忆、已成空白 提交于 2019-12-03 21:47:50

Use boost::mpl::fold like this:

#include <boost/mpl/list.hpp>
#include <boost/mpl/fold.hpp>

#include <iostream>

using namespace boost::mpl;

// Initial state:
struct foo_start {
    template <typename T>
    static void * bar( T *, size_t ) { return 0; }
};

// Folding Step: add This to Prev
template <typename Prev, typename This>
struct foo_iteration {
    struct type {
        template <typename T>
        static void * bar( T * obj, size_t size ) {
            if ( sizeof(This) == size )
                return reinterpret_cast<This*>(obj);
            else
                return Prev::bar( obj, size );
        }
    };
};

// foo is just calling mpl::fold now:
template <typename List>
struct foo : fold< List, foo_start, foo_iteration<_,_> >::type {};

int main() {
    int n = 3;
    void * p = foo< list<char, bool, double, long> >::bar( &n, 4 );
    std::cout << p << std::endl;
}

Prints 0 here, but then I'm on amd64, so I need to change the 4 to an 8, and get something non-zero.

HTH

The MPL is ill-suited for mixed compile-time / run-time operations.

The only operation allowed at runtime on MPL sequences is 'for_each'. For all other situations you should roll your own.

So you should effectively consider that MPL types are not meant to be instanciated.

However, there are other facilities in Boost for such a thing.

The old: Boost.Tuple

The new: Boost.Fusion > http://spirit.sourceforge.net/dl_more/fusion_v2/libs/fusion/doc/html/index.html

Boost.Fusion is a bit more complex (it integrates the concept of views, for example), but would be far better suited to your example.

It does not mean that you should not use the MPL. On the contrary, it is explicitly stated in the Boost.Fusion reference document that one should use MPL algorithms for compile-time computations, and then build the Boost.Fusion container only at the moment you cross the compile-time / runtime boundary (even though Boost.Fusion container are supposed to work with MPL algorithms).

So, keep your mpl implementation transform the resulting list to a Boost.Fusion sequence. Then instantiate the sequence and make use of all the Boost.Fusion facilities.

Warning: haven't done any C++ (meta programming for that matter) in a while, so I might be wrong.

If I understand correctly, your original code finds the first type, which has the same size as does the passed argument and casts the argument to that type. Assuming that, implementing it with mpl would basically boil down to using the find_if algorithm with a custom written predicate to test for type size (see the example in the link above). Just typedef the result, cast it and you're done.

If I understand correctly, you're passing in a T at runtime and hoping that your MPL list of {A, B, C, D} will select and act upon the correct T in that set?

I may be wrong, but this sounds like something suited to Boost.Fusion, which is designed for runtime iteration of compile-time sequences.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!