2012-10-27 6 views
6

まず、私の前の質問hereとの類似点についてお詫びしますが、私は正しいことを尋ねなかったと思います。実行時にboost :: fusion :: vectorをどのように埋めるのですか?

Iメソッドを有する:

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

私のポストをML 'blah'は何ですか? 'blah'は反復ごとに異なる型を持たなければならないので(for recursive template functionを書く必要があるので)、まっすぐなfor-loopはうまく動作しません。挿入する値を表現する方法の例をいくつか教えてください。 – Mankarse

+0

私は、挿入される値が適切な型に適切にキャストされると仮定しています。議論のために、あなたは 'blah'が' int'であると想像することができます。 – arlogb

+0

これらは_runtime_で決定されず、_compile-time_で決定されます。 –

答えて

6

@Mankarseが正しく指定されているように、あなたはfusionコンテナをforループ内に使用​​することはできません。これは、fusionコンテナがすべて約tupleであり、各要素が異なるタイプである可能性があるからです他の要素では、fusionコンテナを反復するすべての関数は実際には2つの関数であり、通常templateまたはオーバーロードされた関数として実装されます。だからfusionコンテナをvectorから初期化するには、そのベクトルにアクセスできる複数の関数(あるいは単純に複数のクラスや関数にコンパイルされるテンプレート)が必要です(少なくともvectorのイテレータと状態コールごとに増加する可能性のある変数)。だから、あなたは2つのオプションがあります:

1)を使用して後押し::融合を::倍:

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>()); 
} 

2番目のケースは、はるかに複雑ですが、そのロジックを理解していれば、あなたがfusionコンテナで何かをするために使用することができ、その選択は見ての通り全てあなたのもの!!

3

あなたはboost::fusion::for_each使用することができます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); 
} 

を、ここでは代わりに、数値インデックスを使用して、いくつかのほとんどが同等のコードは次のとおりです。

#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中にベクトルに索引付けすることができます。 – Mankarse

0

これはいかがですか?

boost :: fusion :: for_each を使用している場合と同様です。

しかし、より速いときに私は<(t)以上です。

使い方

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;} 

これは、ブースト・ユーザーの コピーである http://lists.boost.org/boost-users/2012/08/75493.php http://d.hatena.ne.jp/niitsuma/20120803/1343979718

関連する問題