1ff3ead8   
   From: dave@boostpro.com   
      
   on Fri Apr 20 2012, "Jimmy H." 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   
   > 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   
    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   
    auto throw_if_negative(A&& func, Bs&& ...args)   
    -> decltype(std::forward(func)(std::forward(args)...))   
    {   
    auto res = std::forward(func)(std::forward(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! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|