2013-10-16 61 views
2

我想遍歷任何融合結構的成員,將其成員的類型添加到一個boost :: mpl :: vector(或set)來創建這些類型的boost :: variant。任何幫助表示讚賞。如何增強:: fusion :: for_each添加類型以創建mpl :: vector類型?

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

我不是專家,但我認爲你不能用fusion::for_each來實現你想要的。可以工作的一個非常簡單的替代方法是使用fusion::joint_viewmpl::vector與您的結構(您的結構適應的序列)連接起來。這個聯合視圖不能直接在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; 
} 
+0

謝謝你的建議。這樣可行! – surfcode

+0

順便說一句,如果我有像A,A1,A2這樣的多個類,是否可以「摺疊」上面的類型信息類型2,而不用重新輸入typedef?例如: 'typedef mpl :: fold ,mpl :: insert > :: type types2;'
' typedef mpl :: fold > :: type types3;' boost :: make_variant_over :: type> :: type variant2; – surfcode

+0

抱歉編輯,我的意思是: 'typedef mpl :: fold ,mpl :: insert <...>> :: type type1; typedef mpl :: fold > :: type type2; typedef mpl :: fold > :: type type3; boost :: make_variant_over <... :: type> :: type variant; – surfcode