2012-10-27 55 views
6

首先,道歉與我以前的問題here相似,但我不認爲我問的是正確的事情。如何在運行時填充boost :: fusion :: vector?

我有一個方法:

template <typename T> 
void some_method(T &t) 
{...} 

這需要一個類型fusion::vector<T1, T2, T3, ..., Tn>到在運行時確定 - 例如vector<int, double>在一個呼叫中,vector<int, double, int>在另一個呼叫中。

我想要的東西,如動態填補這一載體:

int blah = 5; 
for(int i = 0; i<size(t); i++){ 
at_c<i>(t) = blah; 
} 

這不起作用,因爲at_c期望一個const

我試過其他的東西(見前面的問題),但仍然無法解決如何實現這一點。

任何幫助非常感謝! 謝謝。

+0

是什麼'blah'?直接for循環將永遠不會工作,因爲'blah'在每次迭代中必須有不同的類型(您需要編寫遞歸模板函數)。你能提供一些你代表要插入的值的例子嗎? – Mankarse

+0

我假設將被插入的值將被適當地轉換爲正確的類型。爲了爭論,你可以想象'blah'是一個'int'。 – arlogb

+0

它們將不會在_runtime_確定,它們將在_compile-time_處確定。 –

回答

6

由於@Mankarse指定正確,你不能在for循環中使用fusion容器,這是因爲fusion容器都是關於tuple,並且每個元素可能具有不同的類型其他元素,遍歷容器的所有函數實際上是一對函數,通常實現爲template或重載函數。所以爲了從vector初始化一個fusion容器,你應該有多個函數(或者簡單地說是一個將被編譯成多個類或函數的模板),它們都可以訪問該向量(或者至少有一個來自vector的迭代器和一個狀態每次呼叫都可以增加的變量)。所以,你有2種選擇:

1)使用boost ::融合::折:

template< class StdIteratorT > 
struct initialize_fusion_container_from_std_iterator { 
    typedef StdIteratorT result_type; 

    template< class T > 
    StdIteratorT operator()(StdIteratorT i, T& val) { 
     val = *i; 
     return ++i; 
    } 
}; 
void use_fold_demo() { 
    int p1[] = {4, 5, 6}; 
    fusion::vector<int, double, int> fv; 
    std::vector<int> sv2(p1, p1 + _countof(p1)); 
    fusion::fold(fv, sv2.begin(), 
    initialize_fusion_container_from_std_iterator<std::vector<int>::iterator>()); 
} 

2)寫一個遞歸調用本身與容器的下一個項目的功能(記住這個函數的語法是像遞歸函數,但它不是遞歸在所有):

// this will be called when we reach end of the fusion container(FIBeginT==FIEndT) 
template< class FIBeginT, class FIEndT, class StdIteratorT > 
void set_fusion_iterator(FIBeginT b, FIEndT e, StdIteratorT i, boost::mpl::true_) 
{ 
} 
// this will be called when FIBeginT != FIEndT 
template< class FIBeginT, class FIEndT, class StdIteratorT > 
void set_fusion_iterator(FIBeginT b, FIEndT e, StdIteratorT i, boost::mpl::false_) 
{ 
    *b = *i; 
    set_fusion_iterator(fusion::next(b), e, ++i, 
     fusion::result_of::equal_to< 
      typename fusion::result_of::next<FIBeginT>::type, FIEndT >()); 
} 

void recursive_function_demo() { 
    typedef fusion::vector<int, double, int> my_fusion_vector; 

    int p1[] = {1, 2, 3}; 
    std::vector<int> sv1(p1, p1 + _countof(p1)); 
    fusion::vector<int, double, int> fv; 
    set_fusion_iterator(fusion::begin(fv), fusion::end(fv), sv1.begin(), 
     fusion::result_of::equal_to< 
      typename fusion::result_of::end<my_fusion_vector>::type, 
      typename fusion::result_of::begin<my_fusion_vector>::type>()); 
} 

正如你看到的第二種情況要複雜得多,但如果你瞭解它的邏輯,你可以用它來與fusion容器做任何事,所以選擇全都是你的!!

3

你可以使用boost::fusion::for_each

#include <boost/fusion/algorithm.hpp> 
#include <boost/fusion/container.hpp> 

struct F { 
    F(int blah): blah(blah){} 
    template <typename T> 
    void operator()(T& t) const { 
     t = blah; 
    } 
    int blah; 
}; 

template <typename T> 
void some_method(T &t) 
{ 
    boost::fusion::for_each(t, F(6)); 
} 

int main() { 
    boost::fusion::vector<int, double, int> idi; 
    some_method(idi); 
    boost::fusion::vector<int, double> id; 
    some_method(id); 
} 

在試圖澄清其for_each,這裏是使用數字索引,而不是一些主要等價代碼:

#include <boost/fusion/algorithm.hpp> 
#include <boost/fusion/container.hpp> 
#include <boost/fusion/sequence.hpp> 

template<typename T, int N, int End> 
struct some_method_impl { 
    void operator()(T& t) const { 
     int blah = 6; 
     boost::fusion::at_c<N>(t) = blah; 
     some_method_impl<T, N+1, End>()(t); 
    } 
}; 

template<typename T, int N> 
struct some_method_impl<T,N,N> { 
    void operator()(T& t) const {} 
}; 


template <typename T> 
void some_method(T &t) 
{ 
    some_method_impl<T,0,boost::fusion::result_of::size<T>::type::value>()(t); 
} 

int main() { 
    boost::fusion::vector<int, double, int> idi; 
    some_method(idi); 
    boost::fusion::vector<int, double> id; 
    some_method(id); 
} 
+0

這非常有幫助。其實你說得很對,我應該更具體地說'blah'... 這是一個'vector ',我想將這個'blah'的值映射到fusion :: vector。你的建議方法有可能嗎? – arlogb

+1

@arlogb:是,[zip](http://www.boost.org/doc/libs/release/libs/fusion/doc/html/fusion/sequence/concepts/random_access_sequence.html)序列連同一組的索引,然後使用索引在'for_each'中索引到vector中。 – Mankarse

0

這個怎麼樣?

這與上述使用 boost :: fusion :: for_each 的情況類似。

但我更快當我<大小(噸)比上面。

使用

main(){ 
    boost::fusion::vector<int,double,std::string,char> vec(9 ,2.2 ,"aaa" ,'b'); 
    std::cout << at_n_dynamic<double>(vec, 1) << std::endl; //=> 2.2 
} 

#include <boost/fusion/include/vector.hpp>  
template<typename V> 
struct fusion_at_n_functor 
{ 
    mutable int i; 
    int n; 
    mutable V value; 
    fusion_at_n_functor(int _n):i(0),n(_n){} 
    void operator()(const V & t) const 
    { if(i==n){value=t;} i++;} 
    template<typename T> 
    void operator()(const T & t) const 
    { i++;} 
}; 

template <typename First,typename Last,typename AtN > void 
at_n_dynamic_fusion_impl(First i,Last last,AtN &atn,boost::mpl::true_){} 
template <typename First,typename Last,typename AtN > void 
at_n_dynamic_fusion_impl(First i,Last last,AtN &atn,boost::mpl::false_){ 
    if(atn.i == atn.n){atn(boost::fusion::deref(i));} 
    else{ 
    atn(boost::fusion::deref(i)); 
    at_n_dynamic_fusion_impl(boost::fusion::next(i),last,atn, 
      boost::fusion::result_of::equal_to< 
      typename boost::fusion::result_of::next<First>::type,Last> ());} 
} 

template <typename Ret,typename Sequence> Ret 
at_n_dynamic(Sequence & seq, int n){ 
    fusion_at_n_functor<Ret> atn(n); 
#if 0 
    // enabling this if is same to the above case of boost::fusion::for_each 
    boost::fusion::for_each(seq, atn); 
#else 
    // this recursion loop stop at n. but boost::fusion::for_each stop at last 
    at_n_dynamic_fusion_impl(boost::fusion::begin(seq),boost::fusion::end(seq) ,atn, 
     boost::fusion::result_of::equal_to< 
      typename boost::fusion::result_of::begin<Sequence>::type, 
      typename boost::fusion::result_of::end<Sequence>::type>());  
#endif 
    return atn.value;} 

這是提升用戶的 副本ML我的帖子 http://lists.boost.org/boost-users/2012/08/75493.php http://d.hatena.ne.jp/niitsuma/20120803/1343979718

相關問題