This question already has answers here:
Should I use std::function or a function pointer in C++?
(6 answers)
Closed 8 years ago.
Is there any differences?
Which is the best way to "save/transfer" function?
function<void(int)> fcn =
[](int par) {std::cout<<"fcn: "<<par<<std::endl; };
void(*fcn_a)(int) =
[](int par) {std::cout<<"fcn_a: "<<par<<std::endl; };
fcn(12);
fcn_a(12);
std::function is more generic - you can store in it any callable object with correct signature (function pointer, method pointer, object with operator()) and you can construct std::function using std::bind.
Function pointer can only accept functions with correct signature but might be slightly faster and might generate slightly smaller code.
In the case of a non-capturing lambda, using a function pointer would be faster than using std::function. This is because std::function is a far more general beast and uses type-erasure to store the function object passed to it. It achieves this through type-erasure, implying that you end up with a call to operator() being virtual.
OTOH, non-capturing lambdas are implicitly convertible to the corresponding function pointer. If you need a full-fledged closure however, you will have to assign the lambda to std::function, or rely on type deduction through templates, whenever possible.
Related
I'd like to build a C++ library which is usable from C as well.
This is the header file I want to be able to compile in C:
typedef void (*log_function_t)(const char *);
typedef void (*delay_function_callback_t)(uint32_t);
typedef void (*delay_function_t)(uint32_t, delay_function_callback_t);
extern "C" void core_init(log_function_t logFunction, delay_function_t delayFunction);
However, since I'm writing the library in C++, it would be nice to work with std::function objects instead of function pointers, so I'd like to call functions like this:
using LogFunction = std::function<void(const char*)>;
using DelayFunctionCallback = std::function<void(uint32_t)>;
using DelayFunction = std::function<void(uint32_t, DelayFunctionCallback)>;
void setLogFunction(const LogFunction& logFunction);
void setDelayFunction(const DelayFunction& delayFunction);
Calling the setLogFunction works just fine, but when I try to call setDelayFunctionit doesn't work.
void core_init(log_function_t logFunction, delay_function_t delayFunction)
{
Utility::getInstance().setLogFunction(logFunction);
Utility::getInstance().setDelayFunction(delayFunction);
}
It says: Reference to type 'const DelayFunction' (aka 'const function<void (unsigned int, function<void (unsigned int)>)>') could not bind to an lvalue of type 'delay_function_t' (aka 'void(*)(unsigned int, void (*)(unsigned int))')
Obviously I understand why it doesn't work, but I have a feeling that it should be possible to solve and I'm just not experienced enough to solve it.
What you're asking seem to be passing a function pointer from C to C++ where the function takes a std::function as argument. I'm afraid this is not possible just as C can't pass a function pointer that takes a std::vector as argument.
When calling Utility::getInstance().setDelayFunction(delayFunction), the ctor of a specialized std::function (i.e. DelayFunction) is matched to construct from a function pointer. However, the match fails because the ctor (of DelayFunction) accepts as its 2nd argument a specialized std::function (i.e. DelayFunctionCallback) , rather than a function pointer (i.e. delay_function_callback_t).
I think the problem lies in the implementation of std::function, which encapsulates the function pointer and erases the latter's type. (See How is std::function implemented?) As a result, a C++ std::function is a different type than a plain-C function pointer.
To workaround this, you could relax the C++-ishness a bit and declare DelayFunction as accepting void(*)(unsigned) instead. I.e., in the C++ file:
using LogFunction = std::function<void(const char*)>;
using DelayFunction = std::function<void(unsigned, delay_function_callback_t)>;
// ^^^^^^^^^^^^^^^^^^^^^^^^^
EDIT: Re. the comment on calling the DelayFunction object from C++, instead of passing a lamba function as the callback (which would fail with the workaround above, since the lambda function can only construct a DelayFunctionCallback, not a delay_function_callback_t), it might be easier to implement the callback as a static member function and use it directly:
Utility::getInstance().delay(delay, (delay_function_callback_t)&Utility::next);
BTW, if Utility is going to store the std::function objects internally, then it may be more efficient to pass-by-value, since the LogFunction and DelayFunction objects will always be constructed anyway (i.e. they are rvalue in core_init).
A void(*)() is fundamentally different from a std::function<void()>.
You can get closer with a void(*)( void* ), void*; a std function has both callable-ness and state, a function pointer only has callable-ness. (std function also carries RTTI and how-to-cleanup-state and how-to-copy-state).
Now you can convert a void(*)() into a std function that is stronger; but not the other way. And the arguments to a function are converted the other way when the call happens.
struct callback {
void* state;
void(*action)(int32_t);
void(*cleanup)(void*);
void*(*copy)(void*);
};
that is the rough C equivalent of a std::function<void(int32_t)>.
The result of an std::bind can be assigned to an std::function
A function pointer can be assigned to an std::function.
So far I was under the impression std::function can generally hold any function pointer. And anything an std::function can hold can be assigned to a function pointer.
And found that the reult of an std::bind can't be assigned to a function pointer
int add(int x, int y)
{
return x+y;
}
int main()
{
std::function<int (int, int)> fp = &add; // a func pointor can be assined to an std::function
int result = fp(3,5) // this works fine
std::function<int (int, int)> add_v2 = std::bind(&add, _1,_2); // std:: bind can be assigned to an std::function
int result = add_v2(3,5); // works fine
int (*add_v3)(int, int);
add_v3 = std::bind(&add, _1,_2); // does not compile
}
Can you please explain why I can't assign the result of std::bind to a function pointr
std::function knows how to invoke calls to multiple callable types, including plain functions, lambdas, and the result of std::bind(). Just because std::function can handle multiple callable types does not means the individual types are interchangeable/assignable with each other.
The return value of std::bind() returns a callable object of an unspecified type determined by the implementation. That type has an operator() that std::function calls. The bound object carries state information about the target object and class method it needs to call inside its operator(). So, by definition, such an object could never be assignable to a plain function pointer. There would be nowhere to store the state data, or even the bound object's own this pointer. The same reasons why a capturing lambda cannot be assigned to a plain function pointer, either.
add_v3 = std::bind(&add, _1,_2); // does not compile
As just the most obvious reason this can't be made to work, consider that all that's left after this line of code executes is a naked pointer. What can it point to?
The resulting bound function (the result of binding add to _1 and _2) clearly didn't exist before this line of code executes. And whatever std::bind created, it's a temporary that will no longer exist after this line executes.
So what could add_v3, a simple raw pointer, possibly point to? What would own it? What would manage its lifetime? When would it be destroyed?
This question already has answers here:
Calling a function through its address in memory in c / c++
(6 answers)
Closed 5 years ago.
I have a function at a known memory address(for example: 0x11111111). The function returns an int, and takes a uint32_t pointer as its only argument.
How would I call this function using c++? I have seen a few examples of calling a function by its address, but I can't seem to find one that takes a pointer as its argument
EDIT:I seen that. Doesn't address how to call the function that takes a pointer as an argument
If you’re sure that there’s a function there, you could call it by casting the address to a function pointer of the appropriate type, then calling it. Here’s C code to do this:
typedef int (*FunctionType)(uint32_t*);
FunctionType function = (FunctionType)0x11111111;
function(arg);
This can easily be modified to support any number of function arguments and any return type you’d like. Just tweak the argument types list of the FunctionType typedef.
Or, in one line (gulp):
(((int (*)(uint32_t *)) 0x11111111)(arg);
This question already has answers here:
Should I pass an std::function by const-reference?
(3 answers)
Should I copy an std::function or can I always take a reference to it?
(5 answers)
Closed 7 years ago.
consider the three functions below,
func1(std::function<size_t(...) > f, ...);
func2(std::function<size_t(...) >& f );
func3(const std::function<size_t(...)> &f);
For any other type of argument passing by value/copy-constructor, passing by reference and passing by const reference have a clear context and their use cases are well known.
For the case of function<> objects, would e.g. passing by const reference save time (from e.g. calling potential copy constructor) or space (no need to pass a whole function object to the stack)? How big is a function object in the first place to make it worth passing passing by const reference? my guess would be that it would roughly be the size of a pointer - is this correct?
Let's take gcc 4.9 and check:
cout << sizeof(int(*)(double, double)) << endl;
cout << sizeof(function<int(double, double)>) << endl;
outputs:
8
32
Size of the callable is, of course, bigger than the pointer size, and you might benefit from passing it by const reference. That is a good idea, however, only if you can guarantee that the object (regardless of it begin an std::function<> or not) you pass by const reference lives as long as you're intending to use it.
For the case of function<> objects, would e.g. passing by const reference save time (from e.g. calling potential copy constructor) or space (no need to pass a whole function object to the stack)?
Maybe. You'd have to measure it.
How big is a function object in the first place to make it worth passing passing by const reference?
It depends on the implementation. You'd have to measure it.
my guess would be that it would roughly be the size of a pointer - is this correct?
Implementations are encouraged to use a "small object optimisation", so that a small function object is stored inside the function object, rather than dynamically allocated. In that case it will be the size of (or slightly larger than) that object. Otherwise, it would be the size of (or slightly larger than) a pointer to the dynamic object.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ return array from function
I am trying to declare a function that returns an array of void pointers. I have the following code:
void *[] get_functions();
However I get the compilation error: expected unqualified-id before '[' token
Is what I'm trying to do valid, and if so what is my syntax error?
EDIT
In reply to some of the comments, I am trying to return an array (which now will probably be a vector) of functions, which I can then randomly select one and call it. What would you suggest instead of void *?
EDIT 2
The type of functions returned will have a fixed signature (not decided yet), Let's for arguments sake say the signature will be int f(int i, int j) what would the return of my get_functions function look like, or will vector<void*> still be appropriate?
C++ doesn't allow a function to return an array. You should probably return a vector instead:
std::vector<void *> get_functions();
There are two issues with your approach. The first of which is that you cannot return arrays from functions. In C you would return a pointer to the elements in the array, but that implies that you need to manage the memory. In C++ you can use a container, like std::vector instead of the array, and that can be returned by value.
The second issue is that you are returning function pointers, and the conversion from function pointer to void* is not guaranteed by the standard. The alternatives here start with returning a function pointer of the appropriate type (i.e. std::vector<int (*)(int,int)>) or using higher level constructs like std::function (C++11, or boost::function in C++03): std::vector<std::function<int(int,int)>>. The first approach is better suited for the description you provided as the types of the functions seem to be fixed and there will be little overhead in using the function pointers. The second approach is more generic as it can encapsulate anything that is callable with two int and return an int, including function pointers and function objects. That in turn allows you to adapt the signatures of other functions by means of std::bind or create lambdas with the appropriate signature: [](int x, int y){ return x*y;}
void **get_functions();
Later on you can then say:
void **pp = get_functions();
pp[5]; // This is the sixth pointer-to-void
If you don't already know the length of the array, you will need to pass it some other way -- for that reason, Jerry Coffin's answer is probably better.
you can just return void pointer to first element of the array. and you can cast it inside the calling function.
the array itself is passed/returned as a pointer.