Boost logo

Boost Users :

Subject: Re: [Boost-users] fusion::result_of::invoke_function_object and references
From: Mike Tegtmeyer (tegtmeye_at_[hidden])
Date: 2009-06-26 21:15:10


I appreciate the reply,

On Jun 26, 2009, at 6:02 PM, Steven Watanabe wrote:
> Strip the references of when you call
> result_of::invoke_function_object.
> You don't need to actually pass anything by value. This is just the
> return
> type calculation.

I guess my problem is that references don't seem to be preserved when
setting up a function object pipeline via fold. Seems there should be
a single copy construct from the return of the function object
invocation to the new state object but a trace results in a couple of
extra state objet copies per invoke_function_object invocation.

Is there something I'm missing?

Again, thanks in advance,
Mike

Attached is something to compile to illustrate my problem-apologies
for the length.

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/fusion/functional/invocation/invoke_function_object.hpp>

#include <iostream>

namespace b = boost;
namespace bf = boost::fusion;

struct my_int {
   my_int(const int &_i=0) :i(_i) {
     std::cerr << "my_int construct with: " << i << "\n";
   }

   my_int(const my_int &rhs) :i(rhs.i) {
     std::cerr << "my_int copy construct with: " << i << "\n";
   }

   my_int & operator=(const my_int &rhs) {
     i = rhs.i;
     std::cerr << "my_int assign with: " << i << "\n";
     return *this;
   }

   ~my_int(void) {
     std::cerr << "my_int destroy\n";
   }

   int operator+(const int &rhs) const {
     return i+rhs;
   }

   int i;
};

std::ostream & operator<<(std::ostream &os, const my_int &rhs)
{
   return (os << rhs.i);
}

// we must return new values here
struct add_1 {
   template <typename Sig>
   struct result;

   template <typename Self, typename T>
   struct result< Self(T) >
   {
     typedef bf::vector<
       typename b::remove_reference<T>::type,int> type;
   };

   template <typename T>
   bf::vector<T,int>
   operator()(const T &t) const
   {
     std::cerr << "ran add_1 with: " << t << "\n";
     return bf::vector<T,int>(t+1,1);
   }
};

std::ostream & operator<<(std::ostream &os, const add_1 &rhs)
{
   return (os << "add_1");
}

// just pass through the values
struct return_2 {
   template <typename Sig>
   struct result;

   template <class Self, typename T, typename U>
   struct result< Self(T,U) >
   {
     typedef bf::vector<
       typename b::remove_reference<T>::type,
       typename b::remove_reference<U>::type
> type;
   };

   template <typename T, typename U>
   bf::vector<T,U>
   operator()(const T &t, const U &u) const
   {
     std::cerr << "ran add_2 with: " << t << "," << u << "\n";

     return bf::vector<T,U>(t,u);
   }
};

std::ostream & operator<<(std::ostream &os, const return_2 &rhs)
{
   return (os << "add_2");
}

struct invoke_filter {
   template <typename Sig>
   struct result;

   template <class Self, typename T, typename State>
   struct result< Self(T,State) >
   {
     typedef typename bf::result_of::
       invoke_function_object<
         typename b::remove_reference<T>::type,
         typename b::remove_reference<State>::type>::type type;
   };

   template <typename T, typename State>
   typename bf::result_of::
     invoke_function_object<T,State>::type
   operator()(T fun, const State &seq) const
   {
     std::cerr << "invoke_filter with: " << fun << "\n";
     return bf::invoke_function_object(fun,seq);
   }
};

int main()
{
   bf::vector<add_1,return_2> seq;

   my_int my = 42;
   bf::vector<my_int> my_vec(my);

   std::cerr << "start\n\n";
   bf::fold(seq,my_vec,invoke_filter());
   std::cerr << "\nstop\n";

   return 0;
}


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