-
-
Save lingxd/ae5e9ca1376c756d50f0083ab1b51b0a to your computer and use it in GitHub Desktop.
C++ lambda expression => C-style function pointer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source: https://stackoverflow.com/a/48368508/17132546 | |
// Entry template | |
// extract the lambda's operaor() function signature | |
template <class F, class T=F> | |
struct lambda_traits: lambda_traits<decltype(&std::remove_reference<F>::type::operator()), F> | |
{}; | |
// For mutable lambda, See https://en.cppreference.com/w/cpp/language/lambda | |
// mutable lambda's operator() is not const, | |
// not mutable lambda's operator() is const | |
template <typename rF, typename F, typename R, typename... Args> | |
struct lambda_traits<R(rF::*)(Args...), F>: lambda_traits<R(rF::*)(Args...) const, F> | |
{}; | |
// Workhorse | |
// every lambda has an unique signature | |
// => lambda_traits will be specialized for every lambda, even if their function signature are the same. | |
template <typename rF, typename F, typename R, typename... Args> | |
struct lambda_traits<R(rF::*)(Args...) const, F> { | |
static auto cify(F&& f) { | |
static rF fn = std::forward<F>(f); | |
return [](Args... args) { | |
return fn(std::forward<Args>(args)...); | |
}; | |
} | |
}; | |
// Wrapper, for convenience | |
template <class F> | |
inline auto lam2fp(F&& f) { | |
return lambda_traits<F>::cify(std::forward<F>(f)); | |
} | |
// usage | |
class A { | |
public: | |
A() { cout << "A()\n"; } | |
A(const A& k) { cout << "A(const A&)\n"; } | |
A(A&& k) { cout << "A(const A&&)\n"; } | |
}; | |
int main() { | |
auto lam_left = [](A& a) {}; | |
auto lam_copy = [](A a) {}; | |
// lambda: left ref args: left ref | |
auto g_left = lam2fp(lam_left); | |
// lambda: left ref args: copy -> right ref | |
auto g = lam2fp(lam_copy); | |
// lambda: right ref args: right ref | |
auto g_right = lam2fp([](A&& a) {}); | |
cout << "----g_left----\n"; | |
A a; | |
g_left(a); | |
cout << "----g----\n"; | |
A b; | |
g(b); | |
cout << "----g_right----\n"; | |
g_right(A()); | |
return 0; | |
} | |
/* output | |
----g_left---- | |
A() | |
----g---- | |
A() | |
A(const A&) | |
A(const A&&) | |
----g_right---- | |
A() | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment