c++ lambda to funtion pointer

通过 traitslambda 转化成函数指针。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Source: https://stackoverflow.com/a/48368508/17132546
#include <iostream>
using namespace std;

// 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:
    using cb_t = void(*)(int);
	A() { cout << "A()\n"; }
	A(const A& k) { cout << "A(const A&)\n"; }
	A(A&& k) { cout << "A(const A&&)\n"; }

    void register_cb(cb_t cb)
    {
        _cb = cb;
    }

    void run()
    {
        if (_cb)
        {
            _cb(_i++);
        }
    }

private:
    int _i {0};
    cb_t _cb {nullptr};
};

struct X
{
    X()
    {
        cout << "X::ctor" << endl;
    }
    int a {0};
};

int main() {
    {
        A a;
        X x;
        cout << "register_cb:-------------------" << endl;

        a.register_cb(lam2fp([&x](int i)
            {
                cout << "i:" << endl;
                cout << "x.a:" << x.a << endl;
            })
        );
        cout << "run1:" << endl;
        a.run();

        cout << "run2:" << endl;
        a.run();
    }

#if 0
	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());
#endif

	return 0;
}
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
// Source: https://stackoverflow.com/a/48368508/17132546
#include <iostream>
using namespace std;

// 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:
    using cb_t = void(*)(int);

	A() { cout << "A()\n"; }
	A(const A& k) { cout << "A(const A&)\n"; }
	A(A&& k) { cout << "A(const A&&)\n"; }

    void run(void(*cb)(int))
    {
        cb(_i++);
    }

private:
    int _i {0};
};

struct X
{
    X()
    {
        cout << "X::ctor" << endl;
    }
    int a {0};
};

int main() {
    {
        A a;
        X x;
        cout << "start:-------------------" << endl;

        cout << "run1:" << endl;
        a.run(lam2fp([&x](int i)
            {
                cout << "i:" << endl;
                cout << "x.a:" << x.a << endl;
            }));

        cout << "run1:" << endl;
        a.run(lam2fp([&x](int i)
            {
                cout << "i:" << endl;
                cout << "x.a:" << x.a << endl;
            }));
    }

#if 0
	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());
#endif

	return 0;
}
william 支付宝支付宝
william 微信微信
0%