[fusion] transform a heterogeneous vector

In the example from the documentation : struct triple { typedef int result_type; int operator()(int t) const { return t * 3; }; }; ... assert(transform(make_vector(1,2,3), triple()) == make_vector(3,6,9)); ...all the elements have the same type. How can it work with heterogeneous vectors ? What would be typedef'ed to result_type ? Jean-Louis

Fusion uses boost::result_of to determine the return type of a call expression. Therefore you just need to define a result-metafunction. struct triple { template<typename Sig> struct result; template<typename Self, typename Arg> struct result<Self(Arg)> { typedef Arg type; }; //... }; -Christopher Jean-Louis Leroy schrieb:
...all the elements have the same type. How can it work with heterogeneous vectors ? What would be typedef'ed to result_type ?
Jean-Louis

Christopher Schmidt wrote:
Fusion uses boost::result_of to determine the return type of a call expression. Therefore you just need to define a result-metafunction. Thanks. It works. However two things bother me.
First there's the warning : 1>c:\program files\boost\boost_1_39\boost\fusion\view\transform_view\detail\deref_impl.hpp(42) : warning C4172: returning address of local variable or temporary 1> c:\program files\boost\boost_1_39\boost\fusion\view\transform_view\detail\deref_impl.hpp(41) : while compiling class template member function 'const int &boost::fusion::extension::deref_impl<boost::fusion::transform_view_iterator_tag>::apply<Iterator>::call(const Iterator &)' 1> with 1> [ 1> Iterator=boost::fusion::transform_view_iterator<boost::fusion::vector_iterator<const boost::fusion::vector<int,int,double,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>,0>,triple2> 1> ] 1> c:\program files\boost\boost_1_39\boost\fusion\iterator\deref.hpp(53) : see reference to class template instantiation 'boost::fusion::extension::deref_impl<boost::fusion::transform_view_iterator_tag>::apply<Iterator>' being compiled 1> with 1> [ 1> Iterator=boost::fusion::transform_view_iterator<boost::fusion::vector_iterator<const boost::fusion::vector<int,int,double,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>,0>,triple2> 1> ] etc etc etc Also, I see that transform returns a view. I need a proper vector that is distinct from the input vector. Here's a bit of context. I am building a recipient for one row in a database query. I have a vector of Exprs, one for each column in the select. Expr has a type member. I want to make a vector with an element for each Expr, initialized to the type's default value (as per type()). I.e. something like this : struct f { /* ... */ template<typename Expr> operator ()(Expr) { return typename Expr::type(); } typedef result_of::transform<SelectList, f>::type row_type; row_type row; transform(select.exprs, row); // type of select.exprs is SelectList std::deque<row_type> results; while (data) { for_each(row, read_fun(...)); results.push_back(row); } Alas row_type is going to be a view :-/ J-L J-L

Comments inline ... Jean-Louis Leroy schrieb:
First there's the warning :
1>c:\program
files\boost\boost_1_39\boost\fusion\view\transform_view\detail\deref_impl.hpp(42)
: warning C4172: returning address of local variable or temporary 1> c:\program
etc etc etc
I assume you return the plain argument type (that is a reference) in your triple2::result meta-function. If that's the case, simply wrap the argument in a remove_reference. E.g. struct triple2 { //... template<typename Self, typename Arg> struct result<Self(Arg)>: boost::remove_reference<Arg> {}; };
Also, I see that transform returns a view. I need a proper vector that is distinct from the input vector. Here's a bit of context. I am building a recipient for one row in a database query. I have a vector of Exprs, one for each column in the select. Expr has a type member. I want to make a vector with an element for each Expr, initialized to the type's default value (as per type()).
I.e. something like this :
struct f { /* ... */ template<typename Expr> operator ()(Expr) { return typename Expr::type(); } typedef result_of::transform<SelectList, f>::type row_type; row_type row; transform(select.exprs, row); // type of select.exprs is SelectList std::deque<row_type> results; while (data) { for_each(row, read_fun(...)); results.push_back(row); }
Alas row_type is going to be a view :-/
simply convert the view (type!) back to a vector using fusion::result_of::as_vector. using namespace boost::fusion; result_of::as_vector<result_of::transform<SelectList,f>::type>::type vec; -Christopher
participants (2)
-
Christopher Schmidt
-
Jean-Louis Leroy