fusion::result_of::invoke_function_object and references
I have another question regarding compilation failures with fusion. If this has been discussed before, can someone please point me to the right location. If not... Is there some reason the application of result_of::invoke_function_object fails to compile for sequence argument references? ie: result_of::invoke_function_object<doit, fusion::vector<int>&>::type Digging a little, it seems that the failure is due to the size<> operator doesn't work with reference types (or is expecting the reference to be stripped prior to this point). I understand that to avoid unnecessary copies, tiers are typically used but in the case where chains of invoke_function_object would like to be strung together where there is an assignment or construction from the actual return value to a variable declared as the type obtained from result_of (in a fold for example), it seems that the vector copy is unavoidable (at least in my reading) unless the argument vector is a const reference. Is this an oversight or am I missing something? Basically I am trying to string together N function objects in the sequence where the ith object gets called with the result of the i-1th object (where each has a different argument list) using fold and I am running into extraneous copies of the return value. I can post a full example if needed. Thanks in advance, Mike error message: /opt/local/include/boost/fusion/sequence/intrinsic/size.hpp:28: error: const boost::fusion::vector<int, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>& is not a class, struct, or union type See code below. #include <boost/fusion/container/vector.hpp> #include <boost/fusion/functional/invocation/invoke_function_object.hpp> namespace b = boost; namespace bf = boost::fusion; struct doit { template <typename Sig> struct result; template <typename Self, typename T> struct result< Self(const T &) > { typedef int type; }; template <typename T> int operator()(const T &t) const { return 1; } }; #if !OK typedef bf::result_of:: invoke_function_object<doit,const bf::vector<int>&>::type result_type2; #else typedef bf::result_of:: invoke_function_object<doit,const bf::vector<int> >::type result_type2; #endif int main() {return 0;}
AMDG Mike Tegtmeyer wrote:
I have another question regarding compilation failures with fusion. If this has been discussed before, can someone please point me to the right location. If not...
Is there some reason the application of result_of::invoke_function_object fails to compile for sequence argument references?
ie: result_of::invoke_function_object<doit, fusion::vector<int>&>::type
Digging a little, it seems that the failure is due to the size<> operator doesn't work with reference types (or is expecting the reference to be stripped prior to this point). I understand that to avoid unnecessary copies, tiers are typically used but in the case where chains of invoke_function_object would like to be strung together where there is an assignment or construction from the actual return value to a variable declared as the type obtained from result_of (in a fold for example), it seems that the vector copy is unavoidable (at least in my reading) unless the argument vector is a const reference.
Is this an oversight or am I missing something?
Basically I am trying to string together N function objects in the sequence where the ith object gets called with the result of the i-1th object (where each has a different argument list) using fold and I am running into extraneous copies of the return value. I can post a full example if needed.
Thanks in advance, Mike
error message: /opt/local/include/boost/fusion/sequence/intrinsic/size.hpp:28: error: const boost::fusion::vector<int, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>& is not a class, struct, or union type
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. In Christ, Steven Watanabe
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; }
participants (2)
-
Mike Tegtmeyer
-
Steven Watanabe