The lambda capture type cannot be controlled by template-dependent names.
However, you could achieve the desired effect by delegating the creation of an internal lambda to an overloaded function:
template<class T> auto make_monad(T&& arg) { return [captive = std::forward<T>(arg)](auto&& a) { std::cout << __PRETTY_FUNCTION__ << " " << a << '\n'; return 1; }; } template<class T> auto make_monad(std::reference_wrapper<T> arg) { return [&captive = static_cast<T&>(arg)](auto&& a) { std::cout << __PRETTY_FUNCTION__ << " " << a << '\n'; return 1; }; } int main() { auto monad = [](auto&& captive) { return make_monad(std::forward<decltype(captive)>(captive)); }; int n = 1; monad(1)(1); monad(n)(2); monad(std::ref(n))(3); }
Outputs:
make_monad(T&&)::<lambda(auto:1&&)> [with auto:1 = int; T = int] 1 make_monad(T&&)::<lambda(auto:1&&)> [with auto:1 = int; T = int&] 2 make_monad(std::reference_wrapper<_Tp>)::<lambda(auto:2&&)> [with auto:2 = int; T = int] 3
I do not want to capture the reference_wrapper by reference, I want to capture the link that it holds by reference. A wrapper link looks best like a link, but since the call operator (operator "a", ".") Cannot be overloaded, at the end of the day it fails.
In this case, you do not need to change the capture type for std::reference_wrapper<T>
. Instead, you may like to capture it by value, like any other argument, and on the usage site, expand the argument first:
template<class T> T& unwrap(T& t) { return t; } template<class T> T& unwrap(std::reference_wrapper<T> t) { return t; } auto monad = [](auto && captive) { return [captive](auto && a) {
source share