c++ forward variadac function arguments to a class constructor - c++

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).

Related

Passing a function as a class field

I have a class(Foo) with a function pointer(fun) as one of its fields. I'm trying to pass a pointer to another function to the class' function pointer so I'll be able to call the outer function using a class method.
#include <functional>
class Foo{
private:
std::function<int(int)>* fun();
public:
Foo(std::function<int(int)>* fun()){
this->fun = fun; //Error: function as left operand
}
void UltraFun(){
this->fun();
}
};
int abc(int x){
//blah blah blah
}
int main(){
Foo f = Foo(&abc)
}
Basically, abc's address should be passed as a parameter in Foo's constructor and assigned to its fun pointer to function. Therefore, whenever I call UltraFun(), abc should be called. But the error I get is in "this->fun = fun" that the left operand is a function.
With
std::function<int(int)>* fun();
you declare fun to be a function that takes no arguments and returns a std::function<int(int)>*. That is probably not what you want.
What you probably want is
std::function<int(int)>* fun;
which makes fun a variable.
Same with the constructor argument, the argument fun is a function that returns a std::function<int(int)>*.
The above is only part of the problem... While &abc is indeed a pointer to a function, it can't be converted to a pointer to a std::function<int(int)>. But it can be used to initialize a std::function<int(int)> object.
You need to make the argument and member variable to not be pointers:
std::function<int(int)> fun;
and
Foo(std::function<int(int)> fun);
Lastly you don't call the function correctly, since it should take an int argument.
You need to pass an argument when calling it:
this->fun(123); // Or some other value
You seem to have some confusion about std::function and function pointers.
std::function<int(int)> * fun(); at class scope declares a function that takes no arguments and returns a std::function<int(int)>*.
std::function<int(int)>* fun() as a function parameter is a function pointer variable (named fun) that points to a function taking nothing and returning a std::function<int(int)>*.
Let's replace std::function<int(int)> with double for clarity:
double* fun(); at class scope declares a function that takes no arguments and returns a double*.
double* fun() as a function parameter is a function pointer variable (named fun) that points to a function taking nothing and returning a double*.
But you do not need to deal with function pointers inside your class at all. std::function does all that for you:
class Foo{
private:
std::function<int(int)> fun;
public:
Foo(std::function<int(int)> fun){
this->fun = fun;
}
void UltraFun(){
this->fun(1); // You must pass an integer!
}
};
https://godbolt.org/z/bW8pq8
std::function<int(int)> can store any function that takes an int and returns an int, you don't need to add more pointers or parentheses or even concern yourself with function pointers. And at no point in this code is it necessary to involve pointers to a std::function.
Note that you intend to deal with a function that takes an int, so you can't just call it without any parameters in UltraFun.
A more limited version without std::function, using function pointers directly instead:
class Foo{
private:
int (*fun)(int);
public:
Foo(int fun(int)){
this->fun = fun;
}
void UltraFun(){
this->fun(1);
}
};
https://godbolt.org/z/JkT9KR

using the 'this' pointer inside a std::function prototype

to my understanding a member function is different to a normal function because there is an additional this pointer parameter.
So my idea is to make is make the following member template function to one of my classes:
template <class T>
void ApplyFunction(function<void(vector<int>&, T)> fun, T val);
and then I will use it inside one of my classes like:
Thing.ApplyFunction(myMethod, this);
and Thing will use the myMethod from my current class instance.
A lot of this code is guesswork so I would like some clarification as to if this would work. Also not sure which way round it is:
void ApplyFunction(function<void(vector<int>&, T)> fun, T val);
or
void ApplyFunction(T val, function<void(vector<int>&, T)> fun);
A code sample describing why I might want something like this:
void ClassA::callbackMethod(vector<int> &array)
{
//I can edit the array here
}
void ClassA::someMethod(void)
{
ClassB B;
B.ApplyFunction(callbackMethod, this);
//now whenever B wants to edit the array, it can by using callbackMethod
B.ComplicatedStuff(); // B uses the callbackMethod multiple times here
}
It looks to me like you are just planning to invoke a method, and you don't need to store the callable. If that is the case you should not use std::function but simply take a callable as a template parameter.
template <class T>
void ApplyFunction(T&& func) {
func(/*pass in your vector here*/);
}
With that you can you can then call it from A by passing in a lambda.
void ClassA::someMethod(void)
{
ClassB B;
B.ApplyFunction([&](std::vector<int>& vec){
// do stuff with vec here
// or call a member function
callbackMethod(vec);
vec.push_back(2);
});
}
This will be faster since passing by template parameter like this gives almost no additional cost from just a normal function call. If the function is inline it can be as cheap as just calling a member function.
std::function is a type-erased wrapper for any callable and comes with overhead, only use it if you need to store the callable for later use.
Edit
If you like to store the function, you don't need a template, you can simply take a std::function as parameter in ApplyFunction.
void ApplyFunction(std::function<void(std::vector<int>&)> func) {
//Store it, call it now or call it later.
m_func = func;
m_func(/*pass in your vector here*/);
}
Call it the same way, with a lambda.
Using a lambda like this is the preferred method when binding a member function to an instance. Instead of passing this separately it's better to wrap it in a lambda and get it for free so to speak.

C++: Store pointer to a member function of an object in another object

I have a class which shall invoke a function specified by the user on certain occasions. Therefore the class has a method void setExternalPostPaintFunction(void(*function)(QPainter&)); that can be used to "register" a function. This function then will be called on that occasion:
class A {
public:
void setExternalPostPaintFunction(void(*function)(QPainter&));
private:
void (*_externalPostPaint)(QPainter&);
bool _externalPostPaintFunctionAssigned;
};
The function pointer is saved in the member variable _externalPostPaint. The implementation of setExternalPostPaintFunction looks like this:
void A::setExternalPostPaintFunction(void(*function)(QPainter&)) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Now, this works with normal functions. However, I want to be able to also pass pointers to member functions of objects. From what I know I also have to pass and store the pointer to the object in this case. However, I don't know which type the other object will have. So I guess I'm forced to use templates. I already thought of something like this:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
void (T::*_externalPostPaint)(QPainter&); //<- This can't work!
bool _externalPostPaintFunctionAssigned;
};
This way I can pass a function pointer and an object pointer to setExternalPostPaintFunction and would probably be able to call the function on the object inside that function. But I'm not able to store it in the variable _externalPostPaint because the type T is only deduced when the function setExternalPostPaintFunction is called, thus I can't have a member variable that depends on this type, since the type of my member variable has to be known when the object is created and apart from that it cannot change, but it would have to in the case when a new function is assigned which possibly could be a member function of an object of different type.
So what is the proper way to do this, or is there any? I'm not super fit with templates and function pointers, so I might have overlooked something.
Anoter option would certainly be to create a functor class with a virtual member function which can be overwritten in a derived class and then pass + store an object pointer of that type instead of the function pointer. But I somehow would prefer my approach if it is somehow possible.
EDIT: SOLUTION
TartanLlama brought me on the right track by suggesting the use of std::function. Here is how I solved it:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(T* object, void(T::*function)(QPainter&)) {
_externalPostPaint = std::bind(function, object, std::placeholders::_1);
_externalPostPaintFunctionAssigned = true;
}
void setExternalPostPaintFunction(std::function<void(QPainter&)> const& function);
private:
std::function<void(QPainter&)> _externalPostPaint;
bool _externalPostPaintFunctionAssigned;
};
As you see, the pointer to the function/member function is stored in an std::function<void(QPainter&)> object now. The advantage is, that an std::function can basically store any callable target. Then there are two overloads: one that can be used for any std::function object that also accepts e.g. a normal function pointer (because the std::function that is expected then is implicitly constructed from that) and one for member functions that have to be called on an object (more for convenience). The latter is implemented as a template. This uses std::bind to create a std::function object of the call of that member function (the user passed) on the object (the user passed).
The overload that takes an std::function is implemented in the source file like this:
void ImageView::setExternalPostPaintFunction(std::function<void(QPainter&)> const& function) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Invoking that stored function in the code of class A is now as simple as that:
//canvas is a QPainter instance
if (_externalPostPaintFunctionAssigned) _externalPostPaint(canvas);
The user who wants to register a member function as callback function just has to do the following:
//_imageView is an instance of "A"
//"MainInterface" is the type of "this"
_imageView->setExternalPostPaintFunction(this, &MainInterface::infoPaintFunction);
Or if it's not a member function but just a normal function:
void someFunction(QPainter& painter) {
//do stuff
}
_imageView->setExternalPostPaintFunction(&someFunction);
Or he can explicitly create a std::function object and pass it:
std::function<void(QPainter&)> function = [&](QPainter& painter){ this->infoPaintFunction(painter); };
_imageView->setExternalPostPaintFunction(function);
Works like a charm.
You could use std::function:
class A {
public:
//PostPaintFun can be anything which acts as a function taking a QPainter&
//Could be a lambda, function pointer, functor, etc.
using PostPaintFun = std::function<void(QPainter&)>;
void setExternalPostPaintFunction(PostPaintFun fun);
private:
//Names beginning with an underscore are reserved, don't use them
//Ending with an underscore is fine
PostPaintFun fun_;
bool externalPostPaintFunctionAssigned_;
};
Now you can use member functions like so:
struct B
{
void exec(QPainter&) const;
};
void foo() {
B b;
a.setExternalPostPaintFunction(
[b] (QPainter& p) {b.exec(p);}
);
}
//or inside B
void B::foo() {
a.setExternalPostPaintFunction(
[this] (QPainter&p) {this->exec(p);}
);
}
I have to say I prefer TartanLlama's answer, but here you have something it could work for you.
This might to need some work, but I'm sure you'll get the idea.
struct IFunctionHolder {}; // Used for pointing to any FunctionHolder
typedef IFunctionHolder* functionHolder_ptr; // Alias for IFunctionHolder* .
template<typename Function> // The template for the actual function holders.
struct FunctionHolder: public IFunctionHolder
{
Function function;
};
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
functionHolder_ptr *function_holder; // This memeber can hold eny instantiation of template<> FunctionHolder.
// Instantiate this member wen calling setExternalPostPaintFunction
bool _externalPostPaintFunctionAssigned;
};
You could have some code like this:
A some_a;
void some_a.setExternalPostPaintFunction(&SomeInstance::some_fnunction); // Here take place the instantiation of FunctionHolder.
some_a.function_holder.function(some_painter);

Using std::function for member functions

My question is about using std::function to class methods. Suppose I have the following class hierarchy:
class Foo {
public:
virtual void print() {
cout << "In Foo::print()" << endl;
}
virtual void print(int) {
cout << "In Foo::print(int)" << endl;
}
};
class Bar : public Foo {
public:
virtual void print() override {
cout << "In Bar::print()" << endl;
}
virtual void print(int) override {
cout << "In Bar::print(int)" << endl;
}
}
Now there is another function which is supposed to dynamically call one of the two class methods depends on its input:
void call(Foo* foo, void (Foo::*func)(void)) {
(foo->*func)();
}
Foo* foo = new Foo();
Bar* bar = new Bar();
call(foo, &Foo::print);
call(bar, &Foo::print);
When I compile the above code snippet using g++/clang++, it works as expected, where the output is:
In Foo::print()
In Bar::print()
My questions are then:
since there are two functions (overloaded) with the same name: print, when I pass the address of class function: &Foo::print, how did the compiler know that I am actually calling Foo::print(void) but not Foo::print(int)?
is there another way that I can generalize the code above such that the second parameter of void call(Foo*, xxx) can be passed using both Foo::print(void) and Foo::print(int)
is there anyway to achieve this feature using new feature in C++11 std::function ? I understand that in order to use std::function with a non-static class method, I have to use std::bind to bind each class method with a specific class object, but that would be too inefficient for me because I have many class objects to be bound.
Since there are two functions (overloaded) with the same name: print, when I pass the address of class function: &Foo::print, how did the compiler knows that I am actually calling Foo::print(void) but not Foo::print(int)?
This is allowed because of [over.over]/p1:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a
pointer to function or a pointer to member function for a specific function from the overload set.
The compiler can use the target type of the parameter-type-list to determine which function from the overload set the pointer-to-member refers:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a
pointer to function or a pointer to member function for a specific function from the overload set. A function
template name is considered to name a set of overloaded functions in such contexts. The function selected
is the one whose type is identical to the function type of the target type required in the context. [ Note: .. ] The target can be
— an object or reference being initialized (8.5, 8.5.3, 8.5.4),
— the left side of an assignment (5.18),
— a parameter of a function (5.2.2),
— [..]
The name Foo:print represents an overload set which the compiler looks through to find a match. The target type Foo::print(void) is present in the overload set, so the compiler resolves the name to that overload.
Is there another way that I can generalize the code above such that the second parameter of void call(Foo*, xxx) can be passed using both Foo::print(void) and Foo::print(int)
There isn't a general way to do it with the name itself. The name has to be resolved to an overload. Instead, try changing the code to accept a function object like a lambda:
template<class Callable>
void call(Foo* foo, Callable&& callback) {
callback(foo);
}
int main()
{
call(foo, [] (Foo* f) { f->print(); f->print(1); });
}
First, std::bind is (almost) entirely outmoded by C++11 lambdas. Don't use std::bind if you can help it. One of these is much clearer than the others, using your example code:
const auto lambda = [=] { foo->print(); }; // Clear!
const auto binderv = std::bind( static_cast<void(Foo::*)()>( &Foo::print ), foo ); // Gets the void version
const auto binderi = std::bind( static_cast<void(Foo::*)(int)>( &Foo::print ), foo, std::placeholders::_1 ); // Gets the int version
//const auto binderv2 = std::bind( &Foo::print, foo ); // Error! Can't tell which Foo::print()
//const auto binderi2 = std::bind( &Foo::print, foo, std::placeholders::_1 ); // Error! Can't tell which Foo::print()
lambda(); // prints "void"
binderv(); // prints "void"
binderi(1); // prints "int"
Second, how does the compiler know which overloaded function to call? The same way it would if you were using non-member functions:
#include <iostream>
void call( void (*fn)() )
{
fn();
}
void print() { std::cout << "void\n"; }
void print(int) { std::cout << "int\n"; }
int main()
{
call( &print ); // prints "void"
}
Only one of those overloaded functions fits the called function's prototype, so the compiler knows. In the case of std::bind above, it can't quite tell, but you can force it with a cast, as I did.
Lambdas or std::function can wrap either of the member functions, but note that you can't overload a function on different std::function signatures. See here.
Update:
The right way to handle your question #3 -- to have one function call functions with drastically different signatures like yours -- is to use some intermediary like a functor (lambda, std::function, std::bind, hand-rolled functor) to erase the differences.
std::function<void()> objects that have the same signature, regardless of what the real functions you're calling have as their signature. std::function is more expensive (in terms of storing and calling) than a lambda but it has the advantage of having a typename that you can use if you need to store it in a container or something. Lambdas can sometimes be inlined away by the compiler if you play your cards right, so efficiency may still favor lambdas.

How to use a class function pointer in another class or struct?

I need to use a function defined in one class in another class. Instead of rewriting the whole function, I tried to pass the function as a pointer, as below:
class C {
public:
int get(int x) { return x*x; }
};
struct S {
int (*func) (int x);
};
int main() {
C c;
S s;
cout << c.get(3) << endl;
s.func = &C::get;
cout << s.func(3) << endl;
return 0;
}
This doesn't work and gives the following error:
func_ptr.cpp: In function ‘int main()’:
func_ptr.cpp:42:18: error: cannot convert ‘int (C::*)(int)’ to ‘int (*)(int)’ in assignment
Is it possible to do something like this, and if so, how can I fix it? Moreover, if it is possible, can I use the pointer from an object instance instead of the class? That is, to possibly use variables defined in a specific class instance. Thanks.
C::get() is a non-static member function, which means it must be invoked on an instance of C. It has an implicit first argument, the this pointer, that must be passed to it when calling the function.
Since your C::get() doesn't seem to need access to any data members of C, you could make it a static member function.
static int get(int x) { return x*x; }
Now your code will work as is.
Another option is to change func so that it is a pointer to a member function of C
struct S {
int (C::*func) (int x);
};
And invoke it as
s.func = &C::get;
std::cout << (c.*(s.func))(3) << std::endl;
Yet another option would be to change the type of S::func to std::function<int(int)>. Now it can hold any callable (function pointer, functor, lambda) that takes a single int as an argument, and returns an int.
struct S {
std::function<int(int)> func;
};
s.func = std::bind(&C::get, &c, std::placeholders::_1);
std::cout << s.func(3) << std::endl;
A regular function and a member function are a bit different. To use a member function, you'll need an object to call it on (i.e. the this pointer in a member function body).
Take a look at std::function and std::bind, they are used to handle function like (callable) entities in a uniform way. They can manage global functions, static member functions, lambdas, regular member functions, functors, whatever that can be called like a function.
http://en.cppreference.com/w/cpp/utility/functional/function
http://en.cppreference.com/w/cpp/utility/functional/bind
http://en.cppreference.com/w/cpp/header/functional
e.g.:
struct S
{
std::function<int(int)> func;
};
C c;
S s;
s.func = std::bind( &C::get, &c, std::placeholders::_1 );
If you're OK with using STL then you can utilize std::function to hold a pointer to a function and std::bind to bind that particular pointer to a particular function. It makes your code look much more cleaner. std::bind looks for both static and non-static member functions. For non-static member function would need to pass the object reference so it will be able to point to the correct address.
Here is a code snippet to show how to use it:
std::bind(ClassName::MemberFunctionName, object, std::placeholders::_1)
std::placeholders::_1 means that ::MemberFunctionName accepts one parameter.