我正在尝试从std :: function中找到函数的地址。
第一个解决方案是:
size_t getAddress(std::function<void (void)> function) {
typedef void (fnType)(void);
fnType ** fnPointer = function.target<fnType *>();
return (size_t) *fnPointer;
}
但是这只适用于具有(void())签名的函数,因为我需要函数 签名是(void(Type&amp;)),我试图做
template<typename T>
size_t getAddress(std::function<void (T &)> function) {
typedef void (fnType)(T &);
fnType ** fnPointer = function.target<fnType *>();
return (size_t) *fnPointer;
}
我得到“错误 - 预期”('用于函数式转换或类型构造“
更新:有没有办法捕获成员类地址?对于我正在使用的班级成员:
template<typename Clazz, typename Return, typename ...Arguments>
size_t getMemberAddress(std::function<Return (Clazz::*)(Arguments...)> & executor) {
typedef Return (Clazz::*fnType)(Arguments...);
fnType ** fnPointer = executor.template target<fnType *>();
if (fnPointer != nullptr) {
return (size_t) * fnPointer;
}
return 0;
}
更新:捕捉lambda我正在使用
template <typename Function>
struct function_traits
: public function_traits<decltype(&Function::operator())> {
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef ReturnType (*pointer)(Args...);
typedef std::function<ReturnType(Args...)> function;
};
template <typename Function>
typename function_traits<Function>::function
to_function (Function & lambda) {
return static_cast<typename function_traits<Function>::function>(lambda);
}
template <typename Lambda>
size_t getAddress(Lambda lambda) {
auto function = new decltype(to_function(lambda))(to_function(lambda));
void * func = static_cast<void *>(function);
return (size_t)func;
}
std::cout << getAddress([] { std::cout << "Hello" << std::endl;}) << std::endl;
答案 0 :(得分:21)
调用target时需要使用template
关键字:
#include <functional>
#include <iostream>
template<typename T>
size_t getAddress(std::function<void (T &)> f) {
typedef void (fnType)(T &);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}
void foo(int& a) {
a = 0;
}
int main() {
std::function<void(int&)> f = &foo;
std::cout << (size_t)&foo << std::endl << getAddress(f) << std::endl;
return 0;
}
提示:当您遇到C ++语法问题时,我建议您使用clang++
来编译代码。如果您如何编写代码,通常指向您的写入方向以修复错误(当它可以弄清楚您在做什么时)。
我还建议您使用可变参数模板使您的函数更通用:
template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
typedef T(fnType)(U...);
fnType ** fnPointer = f.template target<fnType*>();
return (size_t) *fnPointer;
}
答案 1 :(得分:2)
std::function
只是一个对象,虽然伪装成非对象。因此,我们可以获取此对象的地址,这在副本等中是不变的。
要获得指针,我们需要一点点投射。例如,给定函数f1
,我们可以通过执行以下操作来打印隐式指针:
std::cout << "f1: " << *(long *)(char *)&f1 << std::endl;
这是做什么的:
long
s,我们可以将此指针指向long,并获取与函数对象关联的基础地址。鉴于两个std::function<void()>
s f1
和f2
,我们可以执行以下操作:
std::cout << "f1: " << *(long *)(char *)&f1 << std::endl;
std::cout << "f2: " << *(long *)(char *)&f2 << std::endl;
std::function<void()> f1copy = f1;
std::cout << "\nafter copy f1 into f1copy:" << std::endl;
std::cout << "addresses of f1 and f1copy differ: " << &f1 << " " << &f1copy << std::endl;
std::cout << "but underlying pointers identical: " <<
*(long *)(char *)&f1 << " " << *(long *)(char *)(&f1copy) << std::endl;
std::cout << "\n after assign f2 to f1copy" << std::endl;
f1copy = f2;
std::cout << "now the underlying pointer of f1copy matches f2's:" << std::endl;
std::cout <<
*(long *)(char *)&f2 << " " << *(long *)(char *)&f1copy << std::endl;
示例输出:
f1: 4439003784
f2: 4439003912
after copy f1 into f1copy:
addresses of f1 and f1copy differ: 0x7fff572ab970 0x7fff572ab910
but underlying pointers identical: 4439003784 4439003784
after assign f2 to f1copy
now the underlying pointer of f1copy matches f2's:
4439003912 4439003912