Как заполнить 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,

Я пробовал другие вещи (см. Предыдущий вопрос), но все еще не могу понять, как этого добиться.

Любая помощь высоко ценится!
Благодарю.

6

Решение

Как правильно указано @Mankarse, вы не можете использовать fusion контейнеры в for цикл и это потому, что fusion контейнеры все о tuple и каждый элемент может иметь тип, отличный от других элементов, все функции, которые проходят через fusion Контейнер на самом деле пара функций и обычно реализуется как template или перегруженные функции. Таким образом, чтобы инициализировать fusion контейнер из vector у вас должно быть несколько функций (или просто шаблон, который будет скомпилирован для нескольких классов или функций), которые все имеют доступ к этому вектору (или, по крайней мере, итератор из vector и переменная состояния, которая может увеличиваться для каждого вызова). Итак, у вас есть 2 варианта:

1) Используйте boost :: fusion :: fold:

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 контейнеры, так что выбор за вами !!

6

Другие решения

Вы могли бы использовать повышение :: фьюжн :: 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);
}
3

Как насчет этого?

Это похоже на приведенный выше случай использования
повышение :: фьюжн :: 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

0