Does boost help in creating generic function wrappers?

In c++0x, creating a generic function wrapper is a bliss: template <typename Func> class gen_wrapper { Func && func_; public: gen_wrapper(Func && in) : func_(in) {} template <typename ... Prms> /*deduce result here */ operator() (Prms && ... prms) { //Do something special here. //NOTE: we can operate with arguments here too return func_(std::forward<Prms>(prms)...); } }; That's it. But if I don't have C++0x, can boost help here? functional/forward_adapter won't work since it hides function parameters, it only lets you operate with the function. It looks like it may be possible to do that by using boost/preprocessor I'll have to generate a whole lot of overloads with O(2^N) (because of the overload on (T &) or (T const &) for every argument). But it looks pretty dounting. It's basically what forward_adapter had to do. Isn't there a ready-made library that would allow me to generate all of the overloads? Thanks, Andy.

AMDG Andy Venikov wrote:
In c++0x, creating a generic function wrapper is a bliss:
template <typename Func> class gen_wrapper { Func && func_; public: gen_wrapper(Func && in) : func_(in) {}
template <typename ... Prms> /*deduce result here */ operator() (Prms && ... prms) { //Do something special here. //NOTE: we can operate with arguments here too
return func_(std::forward<Prms>(prms)...); }
};
That's it.
But if I don't have C++0x, can boost help here?
functional/forward_adapter won't work since it hides function parameters, it only lets you operate with the function.
What do you mean by "hides function parameters"?
It looks like it may be possible to do that by using boost/preprocessor I'll have to generate a whole lot of overloads with O(2^N) (because of the overload on (T &) or (T const &) for every argument). But it looks pretty dounting. It's basically what forward_adapter had to do.
Isn't there a ready-made library that would allow me to generate all of the overloads?
Just define your wrapper to take references, and wrap it in forward_adapter. This should have exactly the same effect as defining all the overloads yourself. In Christ, Steven Watanabe

Steven Watanabe wrote: <snip>
functional/forward_adapter won't work since it hides function parameters, it only lets you operate with the function.
What do you mean by "hides function parameters"?
Sorry I was unclear. What I mean was that forward_adapter doesn't let you intercept the actual function call. You can store the inner functor in the wrapper which allows a delayed call, but whenever someone calls wrapper(prms...), you won't have a chance to intercept that call. Of course, as you suggest below, one could inject one's own functor in between the inner functor and the forward_adapter, but then one is left to deal with how to solve forwarding problem on one's own.
It looks like it may be possible to do that by using boost/preprocessor I'll have to generate a whole lot of overloads with O(2^N) (because of the overload on (T &) or (T const &) for every argument). But it looks pretty dounting. It's basically what forward_adapter had to do.
Isn't there a ready-made library that would allow me to generate all of the overloads?
Just define your wrapper to take references, and wrap it in forward_adapter. This should have exactly the same effect as defining all the overloads yourself.
Correct me if I'm wrong, but I think it's not going to work when the inner functor has (T const &) parameter. If my wrapper declares everything T &, then it won't be able to accept non-const rvalues whereas the original functor was able to do that.
In Christ, Steven Watanabe
Thanks, Andy.

AMDG Andy Venikov wrote:
Steven Watanabe wrote:
Just define your wrapper to take references, and wrap it in forward_adapter. This should have exactly the same effect as defining all the overloads yourself.
Correct me if I'm wrong, but I think it's not going to work when the inner functor has (T const &) parameter. If my wrapper declares everything T &, then it won't be able to accept non-const rvalues whereas the original functor was able to do that.
If you use forward_adapter, you don't need to handle non-const rvalues. forward_adapter handles the overloading and passes const or non-const lvalues to your function object. In Christ, Steven Watanabe

Steven Watanabe wrote:
Correct me if I'm wrong, but I think it's not going to work when the inner functor has (T const &) parameter. If my wrapper declares everything T &, then it won't be able to accept non-const rvalues whereas the original functor was able to do that.
If you use forward_adapter, you don't need to handle non-const rvalues. forward_adapter handles the overloading and passes const or non-const lvalues to your function object.
I don't think I follow. Let's say that you have a functor f of type F, where it's legal to call it like this: int n = 5; f(n, 10); //compiles fine f(n, n); /compiles fine You seem to suggest I create my own my_wrapper<F> and define an operator() with only references: template <typename Func> class my_wrapper { ....//ignore the problem of generating multiple operator()'s //for different Func arity template <typename T1, typename T2> /*deduce ret type*/ operator() (T1 & in1, T2 & in2) { //Do something useful here return func_(in1, in2); } }; ... and then wrap it in a forward_adapter: template <typename Func> inline forward_adapter<my_wrapper<Func> > wrap(Func const & in) { return forward_adapter<my_wrapper<Func> >(my_wrapper<Func>(in)); } But now this fails to compile: wrap(f)(n, 10); //Fails, because 10 is passed as int const & whereas this used to compile fine: f(n, 10); What am I missing? Thanks, Andy.

AMDG Andy Venikov wrote:
Let's say that you have a functor f of type F, where it's legal to call it like this:
int n = 5; f(n, 10); //compiles fine f(n, n); /compiles fine
You seem to suggest I create my own my_wrapper<F> and define an operator() with only references:
template <typename Func> class my_wrapper { <snip> template <typename T1, typename T2> /*deduce ret type*/ operator() (T1 & in1, T2 & in2); };
... and then wrap it in a forward_adapter:
template <typename Func> inline forward_adapter<my_wrapper<Func> > wrap(Func const & in);
Yes that's exactly what I mean.
But now this fails to compile:
wrap(f)(n, 10); //Fails, because 10 is passed as int const &
Since 10 is passed as int const&, T2 should be deduced as const int. This can't be the problem.
whereas this used to compile fine: f(n, 10);
What am I missing?
Did you include result_of support in your wrapper? The following compiles for me: #include <boost/functional/forward_adapter.hpp> #include <boost/utility/result_of.hpp> struct func { typedef void result_type; void operator()(int&, int) const {} }; template<class F> class wrapper { public: wrapper(const F& f) : f(f) {} template<class Sig> struct result; template<class This, class Arg1, class Arg2> struct result<This(Arg1, Arg2)> : boost::result_of<F(Arg1, Arg2)> {}; template<class T1, class T2> typename boost::result_of<F(T1&, T2&)>::type operator()(T1& t1, T2& t2) const { return f(t1, t2); } private: F f; }; template<class F> boost::forward_adapter<wrapper<F> > wrap(const F& f) { return boost::forward_adapter<wrapper<F> >(wrapper<F>(f)); } int main() { int n = 0; func f; f(n, 10); wrap(f)(n, 10); } In Christ, Steven Watanabe

Steven Watanabe wrote:
... and then wrap it in a forward_adapter:
template <typename Func> inline forward_adapter<my_wrapper<Func> > wrap(Func const & in);
Yes that's exactly what I mean.
But now this fails to compile:
wrap(f)(n, 10); //Fails, because 10 is passed as int const &
Since 10 is passed as int const&, T2 should be deduced as const int. This can't be the problem.
Well, you're absolutely right. I totally missed that T would be imbued with const from the argument. On top of that, my test program was still calling the old wrap function (the one that returned wrapper directly, without using forward_adapter), so I jumped to the conclusion that the compiler error was due to non-const reference. BTW, defining result<> seems to be not necessary, but I think it's a good idea to have it. Sorry for the confusion and Thanks! Andy.

On Thu, Jul 15, 2010 at 4:52 PM, Andy Venikov <avenikov@gmail.com> wrote:
BTW, defining result<> seems to be not necessary, but I think it's a good idea to have it.
Are you sure you're actually calling the function_adaptor object? The result member is necessary as soon as boost::result_of is instantiated, which happens when you invoke the function_adaptor's call operator. Also, you may be interested in an upcoming new feature. When Boost 1.44 is released you will no longer need to define result if your compiler supports C++0x decltype. To enable this new feature define BOOST_RESULT_OF_USE_DECLTYPE before including boost/utility/result_of.hpp. Daniel Walker

Daniel Walker wrote:
On Thu, Jul 15, 2010 at 4:52 PM, Andy Venikov <avenikov@gmail.com> wrote:
BTW, defining result<> seems to be not necessary, but I think it's a good idea to have it.
Are you sure you're actually calling the function_adaptor object? The result member is necessary as soon as boost::result_of is instantiated, which happens when you invoke the function_adaptor's call operator.
Also, you may be interested in an upcoming new feature. When Boost 1.44 is released you will no longer need to define result if your compiler supports C++0x decltype. To enable this new feature define BOOST_RESULT_OF_USE_DECLTYPE before including boost/utility/result_of.hpp.
Daniel Walker
You're right, it is necessary. I just took result<> out and sure enough I get a compiler error inside result_of. I really don't know why I thought yesterday that it compiled fine. Man, too many errors for a test program... :-( Thanks, Andy.

From: boost-bounces@lists.boost.org on behalf of Andy Venikov Sent: Fri 7/16/2010 11:57 AM To: boost@lists.boost.org Subject: Re: [boost] Does boost help in creating generic function wrappers?
On Thu, Jul 15, 2010 at 4:52 PM, Andy Venikov <avenikov@gmail.com> wrote:
BTW, defining result<> seems to be not necessary, but I think it's a good idea to have it.
You're right, it is necessary. I just took result<> out and sure enough I get a compiler error inside result_of. I really don't know why I thought yesterday that it compiled fine. Man, too many errors for a test program... :-(
Rather than being discouraged from having too many errors consider them many opportunities to practice what we know. Stephen
participants (4)
-
Andy Venikov
-
Daniel Walker
-
Steven Watanabe
-
Torri, Stephen CIV NSWCDD, W15