i'm trying to find the address of a function from a std::function.
The first solution was:
size_t getAddress(std::function<void (void)> function) {
typedef void (fnType)(void);
fnType ** fnPointer = function.target<fnType *>();
return (size_t) *fnPointer;
}
But that only works for function with (void ()) signature, since i need for function that signature are (void (Type &)), i tried to do
template<typename T>
size_t getAddress(std::function<void (T &)> function) {
typedef void (fnType)(T &);
fnType ** fnPointer = function.target<fnType *>();
return (size_t) *fnPointer;
}
And i get "Error - expected '(' for function-style cast or type construction"
Update: Is any way to capture member class address? for class members i'm using:
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;
}
Update: To capture lambda i'm using
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;
Address of a function in C or C++ We all know that code of every function resides in memory and so every function has an address like all others variables in the program. We can get the address of a function by just writing the function's name without parentheses. Please refer function pointer in C for details.
You can recover the desired behavior by always using thread-local copies of the std::function because they'll each have an isolated copy of the state variables.
std::bind takes a function as its first parameter and then that function's argument as its parameter. auto add_func = std::bind(&add, _1, _2); auto add_func = std::bind(&add, _1, _2); auto add_func = std::bind(&add, _1, _2);
Function pointers can be useful when you want to create callback mechanism, and need to pass address of a function to another function. They can also be useful when you want to store an array of functions, to call dynamically for example.
You need to use the template
keyword when you call target:
#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;
}
Hint: When you have problems with C++ syntax, I suggest you use clang++
to compile your code. If you play around with how your write the code it will usually point you in the write direction to fix the error (when it can figure out what you are doing).
I also suggest that you use variadic templates to make your function a bit more general:
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;
}
A std::function
is just an object, albeit disguised as not-an-object. So, we can take the address of this object, and this is invariant across copies and such.
To get the pointer, we need a bit of casting. Eg given a function f1
, we can print the implicit pointer by doing:
std::cout << "f1: " << *(long *)(char *)&f1 << std::endl;
What this does is:
long
s, we can derefernce this pointer to long, and get the underlying address associated with the function object.Given two std::function<void()>
s f1
and f2
, we can do things like:
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;
Example output:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With