Re: C++ question about perfect forwarding
on Fri Apr 20 2012, "Jimmy H." <jhartzell42-AT-gmail.com> wrote:
So let's say my platform (POSIX/Linux) supports a number of
functions that take a varying number of args, but return their error
code in C style, oftentimes as negative numbers signal an error
(which you check errno to discover which error) and non-negative
numbers signal success. I want to write a function which will
automatically throw exceptions when they return errors.
This is an example of my imagined use case: int
bytes_written(posix_neg_error_call(write, fd, buf, count));
... where "write" is an OS-level API call, and fd, buf, and count
are the normal arguments. But I want posix_neg_error_call to support
any call that will return some integral type and take any number of
arguments.
I can do it if I already know the number of arguments:
template<typename A, typename B, typename C, typename D, typename E>
E posix_neg_error_call3(A func, B arg1, C arg2, D arg3) { // These C
functions always take args by value
E res(func(arg1, arg2, arg3));
if (res < 0) throw SomeException();
return res;
}
But how do I make this work for any number of arguments using
variadic templates?
Well, the above isn't perfect forwarding, because you lose rvalue-ness
and constness of the arguments... but that probably doesn't matter
much for your system calls, which are not likely to accept references.
It also would require you to explicitly pass the type of every
argument, including the return type. Surely that isn't what you
meant.
Here's one with variadics but no perfect forwarding.
// untested
template<typename A, typename ...Bs>
auto throw_if_negative(A func, Bs ...args)
-> decltype(func(args...))
{
auto res = func(args...);
if (res < 0) throw SomeException(res);
return res;
}
Adding perfect forwarding looks like this:
// untested #2
template<typename A, typename ...Bs>
auto throw_if_negative(A&& func, Bs&& ...args)
-> decltype(std::forward<A>(func)(std::forward<Bs>(args)...))
{
auto res = std::forward<A>(func)(std::forward<Bs>(args)...);
if (res < 0) throw SomeException(res);
return res;
}
HTH-ly y'rs,
--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]