This question already has answers here:
C++ lambda with captures as a function pointer
(9 answers)
Closed 4 years ago.
I have a function getTotal:
int getTotal( const HitMap& hitMap, bool( *accept)(int chan) )
where the second argument is a bool function specifying which members of the container hitMap should be added to the total.
I'm trying to call it with a lambda. This works:
auto boxresult =
getTotal(piHits, [](int pmt)->bool
{ return (pmt/100) == 1;} );
but this doesn't:
int sector = 100;
auto boxresult =
getTotal(piHits, [sector](int pmt)->bool
{ return (pmt/sector) == 1;} );
I get the error
cannot convert ‘main(int, char**)::<lambda(int)>’ to ‘bool (*)(int)’
for argument ‘2’ to ‘int getTotal(const HitMap&, bool (*)(int))’
from my compiler (GCC 4.6.3). I tried [§or] and [=sector] but it didn't make any difference.
What am I doing wrong?
When a lambda has a capture clause it can no longer be treated as a function pointer. To correct, use std::function<bool(int)> as the argument type for getTotal():
int getTotal( const HitMap& hitMap, std::function<bool(int)> accept)
The lambda function with capturing is not what you expect, you can use these ways:
template <typename F>
int getTotal( const HitMap& hitMap, F accept )
{
}
or
int getTotal( const HitMap& hitMap, std::function<bool(int)> accept )
{
}
The template based getTotal has better performance. Read more.
Related
This question already has answers here:
How can I pass a C++ lambda to a C-callback that expects a function pointer and a context?
(4 answers)
Closed 2 years ago.
I am wrapping around a C function from freeRTOS that creates a task and takes its arguments with void pointer in C++. The function looks a little bit like this:
void createTask(TaskFunction_t taskCode, void * args);
So to my understanding to pass 2 arguments to the task I would need to create a struct, cast its address to void*, pass it and then cast it back to the original state like so:
struct Params
{
const int a;
const double b;
};
static void task(void * args)
{
auto params = *static_cast<Params*>(args);
// do something with params.a and params.b
}
int main()
{
Params params{1, 2.2};
createTask(task, static_cast<void*>(¶ms));
}
What would be preferred way of wrapping this function so that I could pass a variable number of arguments of variable types? Should I just leave void * args as an argument or is there something that could be done with templates or maybe tuples to simplify this process a little bit.
In C++11 onwards, you can use something like
static void call_task(void *args) {
auto& f = *static_cast<std::function<void()>*>(args);
f();
}
// note: need this to stay alive!
std::function<void()> f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
CreateTask(call_task, static_cast<void*>(&f));
You need to ensure the lifetime of f is longer than that of the task (just as you would for your Params object).
You can actually avoid std::function altogether, as:
template<typename Func>
void call_func(void *args) {
auto& f = *static_cast<Func*>(args);
f();
}
template<typename Func>
void wrapped_create_task(Func& func) {
CreateTask(call_func<Func>, static_cast<void*>(&func));
}
// you can still use `std::function` here, but you don't have to.
auto f = [&](){
// Any arguments you like here
do_whatever(1, 2, 3)
};
// this works on any object that implements `operator ()`
wrapped_create_task(f)
Again, it's really important that f remains alive for the duration of its execution. You can't put it on a stack that dies before the task does.
This question already has answers here:
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
(2 answers)
Closed 5 years ago.
class foo {
public:
bool operator () (int & i) {
return true;
}
};
int main() {
foo(WhyDoesThisCompile);
return 0;
}
When passing WhyDoesThisCompile (without spaces) to the functor, the program compiles.
Why is this? I tested it on clang 4.0.0.
You are not invoking the functor.
You are declaring a foo, called WhyDoesThisCompile.
Yes, despite the parentheses.
I guess you meant this:
foo()(WhyDoesThisCompile);
// ^^^^^
// temp ^^^^^^^^^^^^^^^^^^^^
// of invocation of op()
// type
// `foo`
… which doesn't.
This question already has answers here:
How to call through a member function pointer?
(2 answers)
Closed 5 years ago.
I'm trying to call a pointer to a member function, which I retrieve from a map. The call th.fpObjHandler(md, evd, tokenIdx) seems erroneous, I've tried various different syntaxes (e.g. .* and ->*), but I cannot seem to get it right. Hopefully somebody here is able to help.
struct TokenHandler
{
int tokenIdx;
eventDataStatus_t (Schema::*fpObjHandler)(MessageData &md, EventDataImpl &evd, int &tokenIdx);
};
Schema::event(MessageData &md, EventDataImpl &evd)
{
int tokenIdx = 0;
std::map<std::string, TokenHandler> tokenHandlerMap;
tokenHandlerMap["timeInterval"] = { -1, &Schema::timeInterval };
// ..
// ....
TokenHandler th = tokenHandlerMap.at(key);
if (th.fpObjHandler != NULL) {
th.fpObjHandler(md, evd, tokenIdx); // THIS RESULTS IN ERROR
//..
//...
}
}
eventDataStatus_t Schema::timeInterval(MessageData &md, EventDataImpl &evd, int &tokenIdx)
{
//..
//...
return OK;
}
Schema.cpp:111:54: error: must use ‘.’ or ‘->’ to call
pointer-to-member function in ‘th.TokenHandler::fpObjHandler (...)’,
e.g. ‘(... ->* th.TokenHandler::fpObjHandler) (...)’
th.fpObjHandler(md, evd, tokenIdx);
^
First you need an instance of the class Schema, then use .* or ->*, something like:
Schema schema;
(schema.*th.fpObjHandler)(md, evd, tokenIdx);
Or, as you are already in a method of Schema:
(this->*th.fpObjHandler)(md, evd, tokenIdx);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
std::bind a bound function
void foo0(int val) { std::cout << "val " << val << "\n"; }
void foo1(int val, std::function<void (int)> ftor) { ftor(val); }
void foo2(int val, std::function<void (int)> ftor) { ftor(val); }
int main(int argc, char* argv[]) {
auto applyWithFoo0 ( std::bind(foo0, std::placeholders::_1) );
//std::function<void (int)> applyWithFoo0 ( std::bind(foo0, std::placeholders::_1) ); // use this instead to make compile
auto applyFoo1 ( std::bind(foo1, std::placeholders::_1, applyWithFoo0) );
foo2(123, applyFoo1);
}
The sample above does not compile giving multiple errors like: Error 1 error C2780: '_Ret std::tr1::_Callable_fun<_Ty,_Indirect>::_ApplyX(_Arg0 &&,_Arg1 &&,_Arg2 &&,_Arg3 &&,_Arg4 &&,_Arg5 &&,_Arg6 &&,_Arg7 &&,_Arg8 &&,_Arg9 &&) const' : expects 10 arguments - 2 provided.
Using the commented line with explicit type does compile. It seems that the type inferred by auto is not correct. What is the problem with auto in this case?
Platform: MSVC 10 SP 1, GCC 4.6.1
The issue is that std::bind treats "bind expression" (like your applyWithFoo0) differently from other types. Instead of calling foo1 with applyWithFoo0 as parameter it tries to invoke applyWithFoo0 and pass its return value to foo1. But applyWithFoo0 doesn't return anything that is convertible to std::function<void(int)>. The intention of handling "bind expressions" like this is to make them easily composable. In most cases you probably don't want bind expression to be passed as function parameters but only their results. If you explicitly wrap the bind expression into a function<> object, the function<> object will simply be passed to foo1 directly since it is not a "bind expression" and therefore not handled specially by std::bind.
Consider the following example:
#include <iostream>
#include <functional>
int twice(int x) { return x*2; }
int main()
{
using namespace std;
using namespace std::placeholders;
auto mul_by_2 = bind(twice,_1);
auto mul_by_4 = bind(twice,mul_by_2); // #2
auto mul_by_8 = bind(twice,mul_by_4); // #3
cout << mul_by_8(1) << endl;
}
This actually compiles and works because instead of passing a functor to twice like you might expect from the bind expressions #2 and #3, bind actually evaluates the passed bind expressions and uses its result as function parameter for twice. Here, it is intentional. But in your case, you tripped over this behaviour by accident because you actually want bind to pass the functor itself to the function instead of its evaluated value. Wrapping the functor into a function<> object is obviously a work-around for that.
In my opinion this design decision is a bit awkward because it introduces an irregularity people have to know about to be able to use bind correctly. Maybe, we'll get another more satisfying work around in the future like
auto applyFoo1 = bind( foo1, _1, noeval(applyWithFoo0) );
where noeval tells bind not to evaluate the expression but to pass it directoy to the function. But maybe the other way around -- explicitly telling bind to pass the result of a functor to the function -- would have been a better design:
auto mul_by_8 = bind( twice, eval(mul_by_4) );
But I guess, now it's too late for that ...
My guess is the parentheses around the std::bind make the parser think you're declaring functions named applyWithFoo0 and applyFoo1.
std::bind returns a functor the type of which auto should be able to detect.
Try this:
int main(int argc, char* argv[]) {
auto applyWithFoo0 = std::bind(foo0, std::placeholders::_1);
//std::function<void (int)> applyWithFoo0 std::bind(foo0, std::placeholders::_1) ); // use this instead to make compile
auto applyFoo1 = std::bind(foo1, std::placeholders::_1, applyWithFoo0);
foo2(123, applyFoo1);
}
I'm sure this has been asked before, but it's just hard to search for...
So, what I've got is a function that accepts a function pointer. This function pointer has, say, 3 arguments. So, I want to pass to another function, the same pointer, but with 2 arguments filled in.
So, something like this:
int func1 (int (*funcptr)(int, int, int)) {
return func2(funcptr(,8,9));
}
int func2 (int (*funcptr)(int)) {
return (*funcptr)(2);
}
EDIT:
Ok so I got this now with the usage of a lambda
int func2(int (*funcptr2)(int)) {
return (*funcptr2)(2);
}
int func1(int (*funcptr1)(int, int, int)) {
return func2(
[funcptr1](int i)->int {
return (*funcptr1)(i,8,9);
}
);
}
But it's giving me
"cannot convert func1(int (*)(int, int, int))::<lambda(int)> to int (*)(int) for argument 1 to int func2(int (*)(int))"
This is called a lambda, and you can do it with newer C++ versions, std::bind, boost::bind or boost::function.
To answer your updated question, a lambda which captures variables (as your lambda does with funcptr1) cannot be converted to a function pointer. Intuitively this makes sense since your lambda must store this captured variable per lambda; whereas there is no way to do that with a function pointer.
The best solution is probably to take an argument of type std::function, which is a wrapper for any callable type:
int func2(std::function<int(int)> funcptr2) {
return funcptr2(2);
}
int func1(std::function<int(int,int,int)> funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
You can also use templates to make your functions work for any callable type:
template <typename F>
int func2(F funcptr2) {
return funcptr2(2);
}
template <typename F>
int func1(F funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
In C, you can't. You would have to pass the function pointer, and the two arguments.
In C++, you can use std::bind (or boost::bind in older versions) to achieve this.