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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With