Perfect forwarding of a callable

  • A+
Category:Languages

I came up with the following code to transform a R()-like into a void()-like callable:

#include <utility>  template<class Callable> auto discardable(Callable&& callable) { return [&]() { (void) std::forward<Callable>(callable)(); }; } //        ^-- is it ok?  int main() {     auto f = discardable([n=42]() mutable { return n--; });     f(); } 

I'm worried about the capture by reference.

  1. Is it well-defined?
  2. Am I guaranteed that callable is never copied and never used after its lifetime has ended?

This is taggued C++14, but applies to all following standards.

 


Lambdas are anonymous structs with an operator(), the capture list is a fancy way of specifying the type of its members. Capturing by reference really is just what it sounds like: you have reference members. It isn't hard to see the reference dangles.

This is a case where you specifically don't want to perfectly forward: you have different semantics depending on whether the argument is a lvalue or rvalue reference.

template<class Callable> auto discardable(Callable& callable) {     return [&] { (void) callable(); }; }  template<class Callable> auto discardable(Callable&& callable) {     return [callable = std::forward<Callable>(callable)] {  // move, don't copy         (void) std::move(callable)();  // If you want rvalue semantics     }; } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: