Boost logo

Boost Users :

From: Ian McCulloch (ianmcc_at_[hidden])
Date: 2005-03-16 12:24:17


Peter Dimov wrote:

> Ian McCulloch wrote:
>> Peter Dimov wrote:
>>
>>> Ian McCulloch wrote:
>>>>
>>>> Yes, if you want to forward to a function but you don't know if it
>>>> takes arguments by value or const reference.
>>>
>>> It doesn't matter. When you forward, you pass to result_of the exact
>>> types of the arguments you are supplying in the function (object)
>>> call, with a reference when the argument is an lvalue.
>>>
>>> int x;
>>> long y;
>>> int const z;
>>> int g();
>>> int & h();
>>>
>>> f(x, y); // result_of<F(int&, long&)>
>>> f(1, x); // result_of<F(int, int&)>
>>> f(z, 4); // result_of<F(int const&, int)>
>>> f( g(), h() ); // result_of<F(int, int&)>
>>>
>>> What is 'f' and how it takes its arguments in the cases above does
>>> not affect how result_of is used.
>>
>> But what happens if F doesn't have an operator() overload that takes
>> F(int const&, int) but only has F(int, int) ? It seems you need to
>> know this in advance.
>
> No, you don't have to know this in advance. It is up to the implementation
> or specialization of result_of<F(...)> to handle these cases and return
> the correct result.

I'm not sure what you mean here. Do you mean that I should make sure that
F::result<F(int, int>) and F::result<F(int const&, int)> are both defined?
Otherwise I don't understand what magic incantions result_of would have to
do to figure it out.

In the following sample program, I have a functor that takes its argument by
const reference, but the apply() function fails because it tries to pass by
value:
/usr/local/include/boost/utility/result_of.hpp: In instantiation of
`boost::detail::get_result_of<negate_f, negate_f ()(int), false>':
resultof_test.cpp:53: instantiated from
`boost::detail::result_of<negate_f, negate_f ()(int)>'
resultof_test.cpp:53: instantiated from `boost::result_of<negate_f (
(int)>'
resultof_test.cpp:53: instantiated from here
/usr/local/include/boost/utility/result_of.hpp:43: error: no type named
`type'
   in `struct negate_f::result<negate_f ()(int)>'

But if I change apply() to use pass by const-reference then it fails if I
try to use it with a functor that uses pass by value. But maybe I am using
result_of incorrectly.

#include <boost/utility/result_of.hpp>

// some example function that passes by const_reference
template <typename T>
struct negate
{
   typedef T const& argument_type;
   typedef T result_type;

   result_type operator()(argument_type x) const { return -x; }
};

// but we don't want to have to specify the parameter types by hand
struct negate_f
{
   template <typename T> struct result {};

   template <typename T>
   struct result<negate_f(T const&)> // exact argument_type of negate<T>
   {
      typedef typename negate<T>::result_type type;
   };

   template <typename T>
   typename result<negate_f(T const&)>::type
   operator()(T const& x) const
   {
      return negate<T>()(x);
   }
};

// generic apply function
// do we pass by value or const reference here?
template <typename Func, typename T>
typename boost::result_of<Func(T)>::type
apply(Func f, T x)
{
   return f(x);
}

int main()
{
   apply(negate_f(), 5);
}

Cheers,
Ian


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