7

So I have a perfect forwarder, and I want to appropriately capture it in a lambda, such that R-values are copied in, and L-values are captured by reference. However simply using std::forward doesn't do the job, as evidenced by this code:

#include<iostream>

class testClass
{
public:
   testClass() = default;
   testClass( const testClass & other ) { std::cout << "COPY C" << std::endl; }
   testClass & operator=(const testClass & other ) { std::cout << "COPY A" << std::endl; }
};

template< class T>
void testFunc(T && t)
   { [test = std::forward<T>(t)](){}(); }

int main()
{
   testClass x;
   std::cout << "PLEASE NO COPY" << std::endl;
   testFunc(x);
   std::cout << "DONE" << std::endl;

   std::cout << "COPY HERE" << std::endl;
   testFunc(testClass());
   std::cout << "DONE" << std::endl;
}

Compiling this with

g++ -std=c++14 main.cpp

Produces the output

PLEASE NO COPY
COPY C
DONE
COPY HERE
COPY C
DONE

In a perfect world, I would like to only have the "COPY C" appear in the rvalue case, not the lvalue case.

My work around would be to use a helper function overloaded for L- and R- values, but I was wondering if there was a better way.

Cheers!

Hounddog
  • 385
  • 1
  • 10

1 Answers1

8

You may use the following:

[test = std::conditional_t<
             std::is_lvalue_reference<T>::value,
             std::reference_wrapper<std::remove_reference_t<T>>,
             T>{std::forward<T>(t)}]

Live Demo

but providing helper function seems more readable

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Seems as good as anything else. Good to know I'm not missing anything :-) Thanks. – Hounddog Jul 14 '15 at 16:19
  • Apparently `[&t]` would suffice provided that you'd forward `t` when used inside the lambda body according to [this](http://stackoverflow.com/a/26831637/4224575) – Lorah Attkins Apr 10 '16 at 11:20
  • I mean assuming the appropriate behavior would be to move rvalues and reference lvalues (I know see the OP wants to copy rvalues) – Lorah Attkins Apr 10 '16 at 11:29
  • 4
    @LorahAttkins: That assumes also that lifetime of lambda is shorter than the captured variable. – Jarod42 Apr 10 '16 at 17:08