Es ist komplizierter ... Intern Lambda-Funktionen, die Variablen erfassen sind keine Funktionen als solche, sind Datenstrukturen. Ich habe keine Lösung gefunden und viele Anfragen und Fragen nicht gelöst, dann habe ich diesen minimalen Code entwickelt, um den Lambda-Zeiger ohne std :: function oder irgendeine andere Standardfunktion oder Abhängigkeit zu umhüllen. Reine C++ 11.
Akzeptiert alle Arten von Lambda-Captures, Argumente durch Verweis, return void und unterstützt Top-Level-Funktionen und Member-Methoden.
// Type checkers
template<typename _Type>
struct IsVoid
{
static const bool value = false;
};
template<>
struct IsVoid<void>
{
static const bool value = true;
};
// Callable signature interfce
template<typename _ReturnType, typename..._ArgTypes>
struct Callable
{
typedef _ReturnType ReturnType;
typedef _ReturnType (*SignatureType)(_ArgTypes...);
virtual _ReturnType operator()(_ArgTypes...args) = 0;
};
// Function and lambda closure wrapper
template<typename _ClosureType, typename _ReturnType, typename..._ArgTypes>
struct Closure: public Callable<_ReturnType, _ArgTypes...>
{
typedef _ClosureType ClosureType;
const _ClosureType closureHandler;
Closure(const _ClosureType& handler)
: closureHandler(handler)
{
}
_ReturnType operator()(_ArgTypes...args) override
{
if(IsVoid<_ReturnType>::value)
closureHandler(args...);
else
return closureHandler(args...);
}
};
// Fuction template selector
template <typename _FunctionType>
class Function
: public Function<decltype(&_FunctionType::operator())>
{
};
// Function, lambda, functor...
template <typename _ReturnType, typename... _ArgTypes>
class Function<_ReturnType(*)(_ArgTypes...)>
{
public:
typedef Function<_ReturnType(*)(_ArgTypes...)> SelfType;
typedef _ReturnType(*SignatureType)(_ArgTypes...);
Callable<_ReturnType, _ArgTypes...>* callableClosure;
Function(_ReturnType(*function)(_ArgTypes...))
: callableClosure(new Closure<SignatureType, _ReturnType, _ArgTypes...>(function))
{
}
// Captured lambda specialization
template<typename _ClosureType>
Function(const _ClosureType& function)
: callableClosure(new Closure<decltype(function), _ReturnType, _ArgTypes...>(function))
{
}
_ReturnType operator()(_ArgTypes... args)
{
if(IsVoid<_ReturnType>::value)
(*callableClosure)(args...);
else
return (*callableClosure)(args...);
}
};
// Member method
template <typename _ClassType, typename _ReturnType, typename... _ArgTypes>
class Function<_ReturnType(_ClassType::*)(_ArgTypes...)>
{
public:
typedef Function<_ReturnType(_ClassType::*)(_ArgTypes...)> SelfType;
typedef _ReturnType(_ClassType::*SignatureType)(_ArgTypes...);
SignatureType methodSignature;
Function(_ReturnType(_ClassType::*method)(_ArgTypes...))
: methodSignature(method)
{
}
_ReturnType operator()(_ClassType* object, _ArgTypes... args)
{
if(IsVoid<_ReturnType>::value)
(object->*methodSignature)(args...);
else
return (object->*methodSignature)(args...);
}
};
// Const member method
template <typename _ClassType, typename _ReturnType, typename... _ArgTypes>
class Function<_ReturnType(_ClassType::*)(_ArgTypes...) const>
{
public:
typedef Function<_ReturnType(_ClassType::*)(_ArgTypes...) const> SelfType;
typedef _ReturnType(_ClassType::*SignatureType)(_ArgTypes...) const;
SignatureType methodSignature;
Function(_ReturnType(_ClassType::*method)(_ArgTypes...) const)
: methodSignature(method)
{
}
_ReturnType operator()(_ClassType* object, _ArgTypes... args)
{
if(IsVoid<_ReturnType>::value)
(object->*methodSignature)(args...);
else
return (object->*methodSignature)(args...);
}
};
Tests:
#include <iostream>
class Foo
{
public:
int bar(int a, int b)
{
return a + b;
}
};
int someFunction(int a, int b)
{
return a + b;
}
int main(int argc, char** argv)
{
int a = 10;
int b = 1;
// Lambda without capturing
Function<int(*)(int)> fn1([] (int b) -> int {
return b;
});
std::cout << fn1(2) << std::endl; // 2
// Lambda capturing variable
Function<int(*)(int)> fn2([a] (int c) -> int {
return a + c;
});
std::cout << fn2(-7) << std::endl; // 3
// Lambda capturing scope
Function<int(*)(int)> fn3([&] (int c) -> int {
return a + c;
});
std::cout << fn3(-5) << std::endl; // 5
// Arguments by reference
Function<void(*)(int&, int)> fn4([] (int& d, int f) {
d = d + f;
});
fn4(a, -3); // Void call
std::cout << a << std::endl; // 7
// Top level function reference
Function<int(*)(int, int)> fn6(someFunction);
std::cout << fn6(a, 4) << std::endl; // 11
// Member method
Foo* foo = new Foo();
Function<int(Foo::*)(int,int)> fn7(foo->bar);
std::cout << fn7(foo, a, 8) << std::endl; // 15
}
richtig funktioniert wih gcc 4.9.
Danke für Ihre Frage.
Verwenden 'std :: function', zB' std :: function f
Um es präzise aussehen zu lassen, können wir Makro verwenden ; 'und dann' F f ([x] (int a, int b) {return a + b;}); ' –