[fusion] transform a vector of values to refs

Hi, I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence. The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that? Current efforts follows: regards Andy Little #include <quan/out/current.hpp> #include <quan/matrix/out/matrix.hpp> #include <quan/operators/binary_operator_functors.hpp> #include <boost/fusion/sequence/io.hpp> #include <boost/fusion/sequence.hpp> #include <boost/ref.hpp> // try to make a function object to wrap references // in fusion style, with boost::ref struct add_reference_wrapper{ template <typename T> struct result{ typedef boost::reference_wrapper<T> type; }; template <typename T> typename result<T>::type operator()(T & t)const { return boost::ref(t); } }; int main() { using boost::fusion::at_c; typedef boost::fusion::vector4< quan::current::A, quan::current::mA, double,double > fusion_sequence_type; fusion_sequence_type sequence( quan::current::A(3), quan::current::mA(2), 1,1 ); std::cout << "before : " << sequence <<'\n'; // This works OK, and and assign the sequence to itself; std::cout << "after : " << boost::fusion::as_vector( boost::fusion::transform( boost::fusion::make_vector( boost::ref(at_c<0>(sequence)), boost::ref(at_c<1>(sequence)), boost::ref(at_c<2>(sequence)), boost::ref(at_c<3>(sequence)) ),sequence, quan::operator_plus_equals() ) ) <<'\n'; //############################################# // But cant make a vector of non const references boost::fusion::as_vector( boost::fusion::transform( sequence,add_reference_wrapper() ) ); //############################################# }

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Hi,
I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence.
The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that?
You can find an example of exactly that on the zip_iterator_fusion branch of boost/iterator/zip_iterator.hpp HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Hi,
I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence.
The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that?
You can find an example of exactly that on the zip_iterator_fusion branch of boost/iterator/zip_iterator.hpp
Yikes. I don't really understand what I am meant to do with that. I will have to study it in more detail. I reckon that a get_ref_vector(fusion::vector) would be quite useful. I guess there isnt much difference to a view though?. Anyway I have continued hacking away and so here is my latest efforts, using fusion to do a dot product of two vectors. Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW: regards Andy Little -------------------------- // Copyright Andrew Little 2006 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See QUAN_ROOT/quan_matters/index.html for documentation. /* dot product of two vectors using fusion. The input vectors are just raw fusion sequences */ #include <quan/out/length.hpp> #include <quan/out/reciprocal_length.hpp> #include <quan/operators/binary_operator_functors.hpp> #include <boost/fusion/sequence/container/vector.hpp> #include <boost/fusion/sequence/conversion/as_vector.hpp> #include <boost/fusion/sequence/intrinsic/at.hpp> #include <boost/fusion/sequence/intrinsic/value_at.hpp> #include <boost/fusion/algorithm/transformation/transform.hpp> #include <boost/fusion/algorithm/iteration/fold.hpp> #include <boost/ref.hpp> #include <cassert> // Couldnt resist this... :-) namespace quan{ namespace fusion{ // This functor needed as fusion::fold sends // its args the opposite way to quan::operator_XX_equals // Lhs in invoked function is assumed to be // a non const boost::reference_wrapper template <typename F> struct reverse_assign_f_args{ template <typename Rhs, typename Lhs> struct result{ BOOST_MPL_ASSERT((boost::is_reference_wrapper<Lhs>)); BOOST_MPL_ASSERT((boost::mpl::not_< boost::is_const<typename Lhs::type> >)); typedef Lhs type; }; template <typename Rhs, typename Lhs> typename result<Rhs,Lhs>::type operator()( Rhs const & rhs, Lhs lhs)const { F f; return boost::ref(f(lhs.get(),rhs)); } }; // more arg reversing template <typename F> struct reverse_f_args{ template <typename Rhs, typename Lhs> struct result{ typedef typename F:: template result< Rhs,Lhs >::type type; }; template <typename Rhs, typename Lhs> typename result<Rhs,Lhs>::type operator()( Rhs const & rhs, Lhs const & lhs )const { F f; f(lhs,rhs); } }; }}//quan::fusion int main() { // The types of the input 'vectors' typedef boost::fusion::vector4< quan::length::mm,int,int,int > seq1_type; typedef boost::fusion::vector4< quan::reciprocal_length::per_m,int,int,int > seq2_type; // Use fusion to work out the type of the result of // the dot product... // First the result sequence of // multiplying the input sequences. typedef boost::fusion::result_of::as_vector< boost::fusion::result_of::transform< seq1_type,seq2_type,quan::operator_times >::type >::type multiplied_seq; // Now the add and accumulate result type deduction part. // Note that need to switch the args for use with my own functors, // (I have been here with boost::is_convertible, so I'll say no more;-)). // I am using + as the 2nd function applied, not +=, as used at runtime // as I am also trying to 'accumulate' the result_type at this stage. typedef boost::fusion::result_of::fold< multiplied_seq, boost::fusion::result_of::at_c<multiplied_seq,0>::type , quan::fusion::reverse_f_args<quan::operator_plus> >::type result_type; // There was a bit of fun and games to get here so ... BOOST_STATIC_ASSERT(( boost::is_same<result_type,double>::value !=0)); // set up the input 'vectors' seq1_type seq1(quan::length::mm(1000),2,3,4); seq2_type seq2(quan::reciprocal_length::per_m(1),2,3,4); // do the dot_product result_type result = boost::fusion::fold( boost::fusion::transform(seq1,seq2,quan::operator_times()), boost::ref(result), quan::fusion::reverse_assign_f_args<quan::operator_plus_equals>() ); assert(quan::compare(result,30,1e-12) ==0); std::cout << result <<'\n'; } -----------------------------

"Andy Little" <andy@servocomm.freeserve.co.uk> wrote <...>
Anyway I have continued hacking away and so here is my latest efforts, using fusion to do a dot product of two vectors. Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW:
A couple of bugs found in my code, as detailed below . ---> Also I found I had to comment out the specialisation of as_vector<0> in < boost/fusion/sequence/conversion/detail/as_vector.hpp> in the Boost Review version to get it to compile OK in GCC4.0.1 I havent tried the CVS version of the file but it looks unchanged relative to my version. regards Andy Little <...>
// more arg reversing template <typename F> struct reverse_f_args{
template <typename Rhs, typename Lhs> struct result{ typedef typename F:: template result< Rhs,Lhs >::type type; }; template <typename Rhs, typename Lhs> typename result<Rhs,Lhs>::type operator()( Rhs const & rhs, Lhs const & lhs )const { F f;
- f(lhs,rhs); + return f(lhs,rhs); ---------------------- <...>
// do the dot_product
- - result_type result = boost::fusion::fold( - + + result_type result = 0; + + boost::fusion::fold( -------------------------------------------------
boost::fusion::transform(seq1,seq2,quan::operator_times()), boost::ref(result), quan::fusion::reverse_assign_f_args<quan::operator_plus_equals>() ); assert(quan::compare(result,30,1e-12) ==0); std::cout << result <<'\n';
} -----------------------------

Andy Little wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
Also I found I had to comment out the specialisation of as_vector<0> in < boost/fusion/sequence/conversion/detail/as_vector.hpp> in the Boost Review version to get it to compile OK in GCC4.0.1
I havent tried the CVS version of the file but it looks unchanged relative to my version.
Hmmm... Could you provide a minimal code that exhibits the problem? Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edu1li$1sf$2@sea.gmane.org...
Andy Little wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote
Also I found I had to comment out the specialisation of as_vector<0> in < boost/fusion/sequence/conversion/detail/as_vector.hpp> in the Boost Review version to get it to compile OK in GCC4.0.1
I havent tried the CVS version of the file but it looks unchanged relative to my version.
Hmmm... Could you provide a minimal code that exhibits the problem?
Sure. Just include the as_vector header. Note this is the review version, not CVS #include <boost/fusion/sequence/conversion/as_vector.hpp> Compiler:
gcc --version gcc (GCC) 4.0.1 (Indiana Concepts release 2) Copyright (C) 2005 Free Software Foundation, Inc. Copyright (C) 2005 Trustees of Indiana University. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
compile output: E:\projects\Test>gcc -I"C:\boost\include\boost-1_33_1" -I"C:/quan/quan-trunk" -c test.cpp C:/boost/include/boost-1_33_1/boost/fusion/sequence/conversion/detail/as_vector. hpp: In static member function 'static typename boost::fusion::detail::as_vector <0>::apply<Iterator>::type boost::fusion::detail::as_vector<0>::call(Iterator)': C:/boost/include/boost-1_33_1/boost/fusion/sequence/conversion/detail/as_vector. hpp:42: error: invalid use of undefined type 'struct boost::fusion::vector<boost ::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void _, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusi on::void_, boost::fusion::void_, boost::fusion::void_>' C:/boost/include/boost-1_33_1/boost/fusion/sequence/container/vector/vector_fwd. hpp:23: error: declaration of 'struct boost::fusion::vector<boost::fusion::void_ , boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusio n::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boos t::fusion::void_, boost::fusion::void_>' E:\projects\Test>

Andy Little wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edu1li$1sf$2@sea.gmane.org...
Andy Little wrote:
"Andy Little" <andy@servocomm.freeserve.co.uk> wrote Also I found I had to comment out the specialisation of as_vector<0> in < boost/fusion/sequence/conversion/detail/as_vector.hpp> in the Boost Review version to get it to compile OK in GCC4.0.1
I havent tried the CVS version of the file but it looks unchanged relative to my version. Hmmm... Could you provide a minimal code that exhibits the problem?
Sure. Just include the as_vector header. Note this is the review version, not CVS
#include <boost/fusion/sequence/conversion/as_vector.hpp>
Sorry I can't reproduce it. I don't have g++ 4.0.1 at the moment. I tried it with VC7.1, VC8.0, G++ 3.4 and Comeau 4.3.3. All the compilers compile it just fine. Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

Andy Little wrote:
"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Hi,
I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence.
The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that? You can find an example of exactly that on the zip_iterator_fusion branch of boost/iterator/zip_iterator.hpp
Yikes. I don't really understand what I am meant to do with that. I will have to study it in more detail. I reckon that a get_ref_vector(fusion::vector) would be quite useful. I guess there isnt much difference to a view though?. Anyway I have continued hacking away and so here is my latest efforts, using fusion to do a dot product of two vectors. Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW:
Yes, definitely! I'll have to ask for documentation though. A simple readme file is ok, plus, lots of comments. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Joel de Guzman" <joel@boost-consulting.com> wrote
Andy Little wrote:
Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW:
Yes, definitely! I'll have to ask for documentation though. A simple readme file is ok, plus, lots of comments.
OK. Bear in mind that its reliant 3 functors, multiply, add, and add-and-assign. In order to be agnostic regarding type deduction schemes ( my own, phoenix, lambda etc), my thought is to present particular versions of the functors implemented using Boost.Typeof. For the assignment one it needs to be implemented in terms of boost::reference_wrapper anyway and with the Lvalue as the right hand argument, which is AFAICS particular to the use of fold in fusion. for example : struct example_multiply{ template <typename A , typename B> struct result{ typedef BOOST_TYPEOF_TPL(A() * B()) type; }; template <typename A, typename B> typename result<A,B>::type operator(A const & a, B const & b) { return a * b; } }; Boost.Typeof will after all be in the next release alongside Boost.Fusion Is that acceptable? regards Andy Little

Andy Little wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote
Andy Little wrote:
Maybe it would be a useful example in the fusion docs?. Anyway here it is FWIW: Yes, definitely! I'll have to ask for documentation though. A simple readme file is ok, plus, lots of comments.
OK. Bear in mind that its reliant 3 functors, multiply, add, and add-and-assign. In order to be agnostic regarding type deduction schemes ( my own, phoenix, lambda etc), my thought is to present particular versions of the functors implemented using Boost.Typeof. For the assignment one it needs to be implemented in terms of boost::reference_wrapper anyway and with the Lvalue as the right hand argument, which is AFAICS particular to the use of fold in fusion.
for example :
struct example_multiply{
template <typename A , typename B> struct result{ typedef BOOST_TYPEOF_TPL(A() * B()) type; };
template <typename A, typename B> typename result<A,B>::type operator(A const & a, B const & b) { return a * b; } };
Boost.Typeof will after all be in the next release alongside Boost.Fusion Is that acceptable?
Sounds good. Okidoki. Cheers, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edv1e0$n73$1@sea.gmane.org...
Sounds good. Okidoki.
Great. I will see if I can get on with it, rather than spend more time mucking about with fusion ;-) regards Andy Little

"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edv1e0$n73$1@sea.gmane.org...
Sounds good. Okidoki.
OK. Its done. Its called fusion_example.zip and in The Boost vault in generic programming directory: http://tinyurl.com/hw7js There may be some typo errors and I could write in more detail, but there should be eneough there to start with anyawy. regards Andy Little

Andy Little wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edv1e0$n73$1@sea.gmane.org...
Sounds good. Okidoki.
OK. Its done. Its called fusion_example.zip and in The Boost vault in generic programming directory:
There may be some typo errors and I could write in more detail, but there should be eneough there to start with anyawy.
Cool! I'll have a look at it as soon as I get some time; possibly over the weekend. Cheers! -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:ee8u3f$rbc$1@sea.gmane.org...
Andy Little wrote:
"Joel de Guzman" <joel@boost-consulting.com> wrote in message news:edv1e0$n73$1@sea.gmane.org...
Sounds good. Okidoki.
OK. Its done. Its called fusion_example.zip and in The Boost vault in generic programming directory:
There may be some typo errors and I could write in more detail, but there should be eneough there to start with anyawy.
Cool! I'll have a look at it as soon as I get some time; possibly over the weekend.
Actually I am now thinking of extending the dot.doc so that it tracks development of a matrix library using fusion, which it now looks is quite feasible and practical at least for small matrices. regards Andy Little

"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Hi,
I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence.
The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that?
You can find an example of exactly that on the zip_iterator_fusion branch of boost/iterator/zip_iterator.hpp
Yikes. I don't really understand what I am meant to do with that. I will have to study it in more detail.
mpl::transform<value_tuple, boost::add_reference<_> > ref_tuple(( value_tuple )); Does that help? -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:87pse2admy.fsf@pereiro.luannocracy.com...
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote
"Andy Little" <andy@servocomm.freeserve.co.uk> writes:
Hi,
I am trying to transform from a fusion vector of values to a fusion vector of non-const references to those values, the ultimate aim being to assign the original sequence from another sequence.
The code below works ok with make_vector, but I want to be able to automate it for any fusion sequence. How can I do that?
You can find an example of exactly that on the zip_iterator_fusion branch of boost/iterator/zip_iterator.hpp
Yikes. I don't really understand what I am meant to do with that. I will have to study it in more detail.
mpl::transform<value_tuple, boost::add_reference<_> > ref_tuple(( value_tuple ));
Yes if it does what it says on the tin :-) Now all I need is a matrix iterator, but I guess I should figure that out myself. regards Andy Little
participants (3)
-
Andy Little
-
David Abrahams
-
Joel de Guzman