|
Boost Users : |
From: Andy Little (andy_at_[hidden])
Date: 2006-09-08 12:50:21
"David Abrahams" <dave_at_[hidden]> wrote
> "Andy Little" <andy_at_[hidden]> 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';
}
-----------------------------
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net