I've been going nuts trying to figure this out. Consider the following code (I'm assuming forward references have been defined):
// Signature representing a pointer to a method call
typedef
void (MyClass::*MyMethod)(int);
class MyClass
{
MyClass();
void method1(int i);
void method2(int i);
void associateMethod(int index, MyMethod m);
}
Given the above, the constructor can do things like the following:
MyClass::MyClass()
{
associateMethod(1, &MyClass::method1);
associateMethod(2, &MyClass::method2);
}
However, I'd like to be able to invoke 'associateMethod' where the second parameter is an anonymous method. However, the following doesn't compile.
associateMethod(3, [this](int) -> void { /* some code here */ }
I get an error about their being no viable conversion from the lambda to MyMethod.
I'm wondering if the lambda syntax needs to include 'MyClass' somewhere but random guesses for the lambda expression such as
MyClass::[this](int) -> void {}
or
[this]&MyClass::(int) -> void {}
don't compile.
Would appreciate any pointers (no pun intended)
Thanks
You can't convert a lambda expression to a class member function pointer and there's no valid syntax to make it look like one1.
Instead of a raw function pointer, you should declare the MyMethod as std::function signature (as was mentioned in the comments):
using MyMethod = std::function<void(int)>;
You can use lambdas then to initialize this parameter then:
MyClass::MyClass()
{
associateMethod(1, [this](int a) { this->method1(a); });
associateMethod(2, [this](int a) { this->method2(a); });
}
1)Lambda functions can be thought as compiler generated callable classes, which take the captures as parameters on construction and provide a operator()() overload with the parameters and body you specify. Hence there's no possible valid conversion to a raw or member function pointer.
user0042's answer seems the way to go but, just for completeness sake, it's worth mentioning that in C++17 captureless lambdas have a constexpr conversion operator to their function pointer type, hence you should(*) be able of converting such a lambda to a member function pointer, via something like:
// ...
void associateMethod(int index, MyMethod m);
template<typename F>
void associateMethod(int index, F m) {
associateMethod( index,
static_cast<MyMethod>(
&MyClass::bindFun< static_cast<void(*)(MyClass*,int)>(m) >
) );
}
private:
template<auto F>
void bindFun(int x){ (*F)(this,x); }
// to be used like
x.associateMethod(0,[](MyClass* this_, int x){ this_->method1(x+1); });
(*) sadly, this compiles in clang but gcc refuses to compile it (I'm going to ask a question about this, you can find it here).
Related
In C++, is there a way to define a function that takes N number of random arguments (number and parameter types could be anything) and in that function, instantiates a class who's constructor expects those arguments. In pseudo-code, something like:
class ClassType {
ClassType(int, string){}
};
void func(Args ...) {
ClassType A(Args);
}
And better yet, define a function pointer for "func"
Yes it is possible. Output of this
#include <iostream>
#include <utility>
struct ClassType {
ClassType(int a, std::string b){
std::cout << a << b;
}
};
template <typename...Args>
void func(Args&& ... args) {
ClassType A(std::forward<Args>(args)...);
}
int main() {
func(12,std::string("foo"));
}
is
12foo
However, it isnt quite clear why you want func to be variadic when ClassTypes constructor only accepts int,string. Calling func with any other combination will fail.
And better yet, define a function pointer for "func"
You cannot have a function pointer to a template (you also cannot have a function pointer to a whole set of overloads). Thats not how function pointers work. What you can do is taking a function pointer to one particular instantiation of func:
auto fptr = &func<int,std::string>;
If you need some function like object that you can pass around then you can use a generic lambda instead of a bare function pointer (since C++17 I believe):
auto flamb = [](auto&&...args){ func(std::forward<decltype(args)>(args)...); };
This works because the lambda is of some type (albeit unnamed and unspecified) and only its operator() is templated. Hence you can pass such lambda around and only when actually calling it the respective operator() is instantiated. Though, also with that you can only call it with the right parameters (int and std::string).
This question already has answers here:
C++ lambda with captures as a function pointer
(9 answers)
Closed 6 years ago.
The following code does not compile:
typedef void(*RunnableFun)(int); //pointer-to-function type
void foo(RunnableFun f) {
}
void bar(const std::string& a) {
foo([&](int) -> void { std::cout << a; });
}
and IntelliSense is telling me
no suitable conversion function from "lambda []void (int)->void" to "RunnableFun" exists
and the compiler is complaining
'void foo(RunnableFun)' : cannot convert argument 1 from 'bar::<lambda_796873cf40a6be4e411eb9df14f486bf>' to 'RunnableFun'
But the following does compile:
typedef void(*RunnableFun)(int); //pointer-to-function type
void foo(RunnableFun f) {
}
void bar(const std::string&) {
// Notice the empty capture list
foo([](int) -> void { std::cout << "dummy"; });
}
How can I keep the signature of foo() but achieve what I tried in to in the first code example?
P.S.: Changing foo's signature to void foo(std::function<void(int)> f) would compile but can I do it without changing it?
You could take a look at most of the standard library algorithm functions. When they take a "predicate" (callable object) they do it as a template arguments.
So you could make your function as a template:
template<typename FunctionType>
void foo(FunctionType f) {
}
No other change is needed.
It's either this or using std::function, you can't solve your problem without changing the foo function.
A pointer to function only stores a location of execution, it stores no additional state. The only change between executions must be determined by global state.
In your case, you want the lambda to capture local state. So when called after a="hello" it prints a different value than when called after a="world".
The short answer is "Too bad, so sad, but no".
You can hack a bit. You could store a in a static std::string ga; and accessmit within the lambda. Note that this is ugly, not reentrant, exposes your code to global state needlessly, and generally a bad idea.
void bar(const std::string& a) {
static std::string ga;
ga = a; // note, separate line
foo([](int) -> void { std::cout << ga; });
}
Generally pure function pointer callback APIs are a sign an ignorant fool designed the API: a proper C-style callback takes a void*, and a proper C++ callback is a std::function or template callable or similar. (Ignorant as they are not aware that the void* pattern is common: fool because even if you did not know of it, they did not work it out themselves after trying their system a few times and noticed the big gaping hole. It is ok: most programmers are fools until they make all the mistakes themselves!)
If you actually have a void* or equivalent argument you get called back with, you omitted it from your question, and the answer is entirely different. Just store a ptr-to-lambda in that void*, and store a stateless lambda that casts-and-calls the stateful lambda from the void*.
Fairly simple question:
I have a class that uses a (variable) heuristic function to perform a certain algorithm. This heuristic function should ideally be fed to the class constructor as some sort of pointer and implement the following declaration:
int heuristic_Function(GridLocation a, GridLocation b);
What is the best way to accomplish this? Ideally I would like to avoid additional classes and keep the code fairly self-contained (and yes, I am aware of things like delegates and the strategy pattern).
(This has probably been asked hundreds of times already but in different terms)
Well, as you said, you could store a function pointer:
struct Algo
{
using HeurFn = int(GridLocation, GridLocation);
Algo(HeurFn * heuristic) : heuristic_(heuristic) {}
void Run()
{
// use "heuristic_(a, b)"
}
HeurFn * heuristic_;
};
Then instantiate it:
extern int my_fn(GridLocation, GridLocation);
Algo algo(my_fn);
algo.Run();
An alternative would be to pass the function directly to Run, in which case you could make Run a template and perhaps allow for inlining of the actual heuristic code, but you explicitly asked for the heuristic to be configured via the constructor.
Instead of old C function pointer, I would recommend std::function.
So you could write it like this
#include <functional>
struct algorithm{
algorithm (std::function<int(GridLocation, GridLocation)> heuristic_function) :
heuristic(heuristic_function) {}
int do_something (GridLocation a, GridLocation b){
return heuristic(a,b);
}
private:
std::function<int(GridLocation, GridLocation)> heuristic;
}
Advantages are the better readable syntax, and that the caller can use std::bind expressions.
Or you could just take the heuristic as a template, but then you would to either make your algorithm to just a function or write the type to every new instance. See https://stackoverflow.com/a/2156899/3537677
Things get really simple if only the method that does the computations needs the function, and you can forgo storing the function in the class itself. You can then parametrize the method on the type of the passed function, and you get full flexibility:
struct Calculate {
template <typename F> int run(F && f) {
return f(1, 2);
}
};
int f1(int, int) { return 0; }
struct F2 {
int operator()(int, int) { return 0; }
};
int main() {
Calculate calc;
// pass a C function pointer
calc.run(f1);
// pass a C++98 functor
calc.run(F2());
// pass a C++11 stateless lambda
calc.run(+[](int a, int b) -> int { return a-b; });
// pass a C++11 stateful lambda
int k = 8;
calc.run([k](int a, int b) -> int { return a*b+k; });
}
You don't need to manually spell out any types, and you can pass function-like objects that can be stateful.
The power of C++11 comes from the && syntax. There's more to it than meets the eye. In run's parameter, F is a deduced type, and && is a universal reference. That means that, depending on the context, it acts either as an lvalue-reference we know from C++98, or as an rvalue-reference.
The + operator applied to the lambda stresses that it is in fact stateless. Its uses forces a conversion from the abstract lambda type to a C function pointer. The type of the +[](int,int)->int {...} expression is int(*)(int,int). The use of the + operator is not necessary, I've only used it to underline the statelessness.
Comment: I'm posting this question again, since some people requested me to post the full code. Here it is:
I have a function pointer typedef that looks like this:
template<typename USER_DATA>
class RowProcessor
{
typedef void (*RowFunction)(USER_DATA, std::vector<USER_DATA> &);
RowProcessor(RowFunction, int) {};
};
and then I'm using in another class UseRowProcessor:
class UseRowProcessor {
public:
void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
void UseRowProcessor::AddUserData(SomeClass c, std::vector<SomeClass> &v) {
v.push_back(c);
}
void UseRowProcessor::LoadUserData() {
RowProcessor<SomeClass> myRowProcessor(AddUserData, 1); // ERROR!!
}
So the error occurs when calling RowProcessor's constructor.
The full error message says that
no insatnce of constructor "RowProcessor<USER_DATA>::RowProcessor [with USER_DATA=SomeClass]" matches the argument list
argument types are: (void (SomeClass c, std::vector<SomeClass, std::allocator<SomeClass>> &v), std::vector<SomeClass, std::allocator<SomeClass>>)
, which I have no idea what it says except for the fact that the constructor arguments do not match..
Why doesn't my AddUserFunction match the function pointer typedef??
TEST LINK<<<<<<<<
Change the function:
void AddUserData(SomeClass, std::vector<SomeClass> &);
to static void AddUserData(SomeClass, std::vector<SomeClass> &); .
As it is a class member function, the this parameter will be added after compiler, so it is not the type of the function pointer. By changing it to static, no this parameter will be added.
As Matt said you need a static function to get this working
class UseRowProcessor {
public:
static void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
Here's the completely fixed sample (there were some more issues after fixing to static).
Member functions are different from ordinary functions and this carries over to their type. There is a set of work-arounds that enable you to pass member function pointers to functions that take ordinary function pointers as their parameters, but if you have control over the code you should take a different path. Instead of accepting a function pointer accept a functor.
template<typename Functor>
int f(Functor func) {
// use func like you would a function, e.g. call it with arguments func(1, 2)
}
Now you can call f with a lambda, function object, member function pointer (after you bound it to this), or function pointer.
If you want to avoid templates, accept a std::function instead, but this should only be done if you have special reasons for it.
I don't know if what I am trying to do is possible but it would be grate to be. It will really prove that C++ is a strong language.
So, I have a DLL and an EXE that uses a function exported by the DLL. That function takes an argument which is, or must be a pointer to another function, and executes it. Something like this:
extern void RunFunction(void (*FunctionPonter)()) {
(*FunctionPonter)();
}
and I call it like this:
RunFunction(&FunctionToExecute);
The function sent as an argument will not have arguments, just a void function.
So, all this works, as it is presented here. Now, I would like to go further and define (*void)() as, for example, Action.
typedef (*void)() Action;
Action FunctionToExecute() {
// My code. This function won't return results - void
}
and I would like to send the pointer to the function in my DLL like this:
// This is how it would be declared now in the DLL
extern void RunFunction(void (ACTION) {
(*FunctionPonter)();
}
// and this is how I would like to use it
RunFunction(FunctionToExecute);
I am using VC2010 and I don't know how could I do that, if it is possible. Thanks for your ideas, explanations and help!
Firstly, the proper syntax for function type typedef is
typedef void (*Action)();
Secondly, typedef-name for function type can be used to declare functions of that type, but they cannot be used to define such functions. I.e. if FunctionToExecute is the function you wat to execute through the pointer, then it has to be defined as
void FunctionToExecute() {
/* whatever */
}
The calling function would be defined as
void RunFunction(ACTION p) {
p();
}
And the call to it would look as follows
RunFunction(FunctionToExecute);
That's it. Unary * and & operators are optional with function pointers.
Ok, if I understand your question correctly, you're looking for a way to only allow certain functions to be passed as arguments to your DLL function.
Using a typedef won't work, as that just creates an alias; Action and void (*)() are indistinguishable to the compiler in your code. Instead, you'll have to create a brand new type. In C++, you should strongly consider using a functor:
// Abstract functor
struct Action {
virtual void operator() () const = 0;
};
// The DLL function
void RunFunction(const Action &action) {
action();
}
// Define your function as a derived functor
struct FunctionToExecute : Action {
void operator() () const { std::cout << "Hello\n"; }
};
// Run a function
RunFunction(FunctionToExecute());
Demo: http://ideone.com/5pl23.