如何提升:: fusion :: for_each添加类型来创建类型的mpl :: vector?

时间:2013-10-16 00:49:46

标签: c++ boost metaprogramming boost-mpl

我想遍历任何fusion结构的成员,将其成员的类型添加到boost :: mpl :: vector(或set)以创建这些类型的boost :: variant。任何帮助表示赞赏。

struct A
{
    int a1;
    double a2;
    float a3;
};

BOOST_FUSION_ADAPT_STRUCT(
    A,
    (int,a1)
    (double,a2)
    (float,a3)
)

struct StructTypes
{
    template <typename T>
    void operator()( T& t ) const 
    {
        // how do I append to a list of types here?
    }
};

int main()
{
    A a;
    boost::fusion::for_each( a, StructTypes() );
}

1 个答案:

答案 0 :(得分:1)

我不是专家,但我认为你无法使用fusion::for_each完成你想要的任务。一个非常简单的替代方法是使用fusion::joint_viewmpl::vector与您的struct(您的struct适应的序列)连接起来。此联合视图不能直接在boost::make_variant_over中使用,但可以使用fusion::result_of::as_vector来获取具有相同元素的fusion::vector,从而轻松解决此问题。这种方法的一个问题(我不确定它真的是一个问题,但它无疑是丑陋的)是,如果你的向量和结构之间有共同的元素,那么结果变量将在它的列表中有两个这样的元素类型。如果要解决此问题,可以使用mpl::set代替向量,然后使用mpl::fold<A, mpl::set<your types...>, mpl::insert<_1,_2> >::type。这为您提供了mpl::set,没有任何重复的类型。您需要再次使用fusion::result_of::as_vector才能使用make_variant_over

Running on Coliru

#include <iostream>
#include <string>

#include <boost/variant.hpp>

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/mpl.hpp> //important: allows compatibility fusion-mpl
#include <boost/fusion/include/joint_view.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/set.hpp>
#include <boost/fusion/include/fold.hpp>
#include <boost/fusion/include/for_each.hpp>


#include <boost/mpl/fold.hpp>
#include <boost/mpl/set.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/insert.hpp>

namespace fusion=boost::fusion;
namespace mpl=boost::mpl;

struct A
{
    int a1;
    double a2;
    float a3;
};

BOOST_FUSION_ADAPT_STRUCT(
    A,
    (int,a1)
    (double,a2)
    (float,a3)
)

struct printer
{
    template <typename T>
    void operator()(T) const
    {
        std::cout << typeid(T).name() << ";";
    }
};


int main()
{
    typedef fusion::result_of::as_vector<fusion::joint_view<mpl::vector<bool,std::string>,A> >::type  types1;
    typedef boost::make_variant_over<types1>::type variant1;

    variant1 a = 3.5f;
    variant1 b = true;

    std::cout << a << " " << b << ". " << fusion::result_of::size<variant1::types>::type::value << " elements in the variant" << std::endl;
    fusion::for_each(variant1::types(),printer());
    std::cout << std::endl;

    typedef mpl::fold<A,mpl::set<std::string,int>,mpl::insert<mpl::_1,mpl::_2>>::type types2;
    typedef boost::make_variant_over<fusion::result_of::as_vector<types2>::type>::type variant2;

    variant2 a2 = 4;
    variant2 b2 = "bla"; 

    std::cout << a2 << " " << b2 << ". " << fusion::result_of::size<variant2::types>::type::value << " elements in the variant" << std::endl;
    fusion::for_each(variant2::types(),printer());
    std::cout << std::endl;
}