I have two classes, Foo and Bar. Class Foo contains an instance of class Bar called b and class Bar needs to access the member function FooFunc of class Foo. Function FooFunc performs some arithmetic, but for now I just want to try to pass it but I can't seem to make the following MWE (named scratch.cpp) work:
#include <iostream>
class Foo; // forward declaration
class Bar
{
public:
Bar() {}
void BarFunc(double (Foo::*func)(double))
{
std::cout << "In BarFunc \n";
}
};
class Foo // must be declared after Bar, else incomplete type
{
public:
Foo() {}
Bar b;
double FooFunc(double x)
{
return x + 1;
}
void CallBarFunc()
{
b.BarFunc(FooFunc); // error occurs here
}
};
int main()
{
Foo f;
f.CallBarFunc();
}
The error I get is
scratch.cpp:27:22: error: no matching function for call to ‘Bar::BarFunc(<unresolved overloaded function type>)’
scratch.cpp:27:22: note: candidate is:
scratch.cpp:9:8: note: void Bar::BarFunc(double (Foo::*)(double))
scratch.cpp:9:8: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘double (Foo::*)(double)’
Unlike non-member functions, which decay to a function pointer, non-static member functions don't decay to a pointer.
Instead of:
b.BarFunc(FooFunc);
Use:
b.BarFunc(&Foo::FooFunc);
Related
I am trying to pass a bound member function as an std::function while hiding the std::bind_front invocation in a base class. Minimal example:
#include <functional>
static void runIt(std::function<void()> f) { f(); }
template<typename T>
struct Base {
using PFn = void (T::*)();
void run(PFn fun) { runIt(std::bind_front(fun, this)); }
};
struct Derived : Base<Derived> {
void main() { run(&Derived::func); }
void func() {}
};
Unfortunately, the compiler does not like it:
static void runIt(std::function<void()> f)
No matching function for call to 'runIt' clang(ovl_no_viable_function_in_call)
test.cpp(12, 19): In instantiation of member function 'Base<Derived>::run' requested here
test.cpp(3, 13): Candidate function not viable: no known conversion from 'std::__perfect_forward_impl<std::__bind_front_op, std::__tuple_types<void (Derived::*)(), Base<Derived> *>, std::__tuple_indices<0, 1>>' to 'std::function<void ()>' for 1st argument
What am I missing?
You can't std::invoke(fun, this) since this is of type Base<Derived>* and the function pointer is of type void (Derived::*)() (And Derived is not a base of Base<Derived>, but the other way around).
Either upcast the pointer to member function or the pointer to the object. Preferably the object pointer:
runIt(std::bind_front(fun, static_cast<T*>(this)));
struct A
{
void f1()
{
f2(); // ok, though f2() is not declared before
}
void f2()
{}
void f3(X*) // error: unknown type name 'X'
{}
struct X
{};
};
int main()
{
A a;
}
Why do member types need to be forward declared while member functions needn't?
This has to do with the complete-class context. When you are in the body of a member function, the class is considered complete and can use anything defined in the class, no matter where in the class it is declared.
The function parameters are not part of that context so they must be types that are known about at the point you try to use them.
First, I apologize for the vague title of the question. Consider the following example:
class A {
public:
virtual void foo() const = 0;
void foo(int n) const {
while(n--)
foo();
}
};
class B: public A {
public:
void foo() const override {
std::cout << "B::foo()" << std::endl;
}
};
int main() {
auto obj = B{};
obj.foo();
obj.foo(10);
}
Basically I want to have two versions of the method foo in class A (and any child class). The one without argument has to be defined by the child (hence it it declared as pure). But, the one with an integer does not need to be redefined by every child (as the functionality is the same: call the no-argument version n times.)
However the above code does not compile, giving the following error:
g++ -D_GLIBCXX_DEBUG -std=c++11 example.cpp -o example
example.cpp: In function ‘int main()’:
example.cpp:31:15: error: no matching function for call to ‘B::foo(int)’
31 | obj.foo(10);
| ^
example.cpp:21:14: note: candidate: ‘virtual void B::foo() const’
21 | void foo() const override {
| ^~~
example.cpp:21:14: note: candidate expects 0 arguments, 1 provided
Why this happens? What is wrong in my reasoning? For example if I rename the method with signature int foo(int) to something like int foo2(int)' and then callfoo2` from the child everything works fine.
This is how name lookup works. When a derived class like B has its own member function foo, it hides all foo member functions of its base classes, orthogonal to virtual-ness and function parameter, i.e., it hides the overload set. You can, however, explicitly pull them in. In the public: section of class B, add:
using A::foo;
Consider the following. Class A has a function pointer as a member and accepts a function in its constructor to pass to this member. In a separate file, I have a class B that contains a pointer to class A as a member, and class B also has as a member the function I want to pass to class A.
Below is an example and the errors I receive. What's the standard method of doing something like this?
A.h:
class A {
private:
int (*func)(int);
public:
A(int (*func_)(int));
};
A::A(int (*func_)(int)) : func(func_) {}
B.h:
#include "A.h" // Why can't I forward declare A instead?
class B {
private:
A *A_ptr;
int function(int); // some function
public:
B();
~B();
};
int B::function(int n) {
return n+2; // some return value
}
B::B() {
A_ptr = new A(function);
}
B::~B() {
delete A_ptr;
}
main.cpp:
#include "B.h"
int main() {
B b;
}
Errors I get:
B.h: In constructor ‘B::B()’:
B.h:18:25: error: no matching function for call to ‘A::A(<unresolved overloaded function type>)’
B.h:18:25: note: candidates are:
A.h:9:1: note: A::A(int (*)(int))
A.h:9:1: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘int (*)(int)’
A.h:1:7: note: A::A(const A&)
A.h:1:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘const A&’
To answer your question regarding "What's the standard method of doing something like this" I'll assume you mean passing member functions and/or general function pointers around and executing them with some data. Some popular implementations which provide this ability are:
FastDelegate
std::function
boost::function
It really comes down to preference and library choice. Personally, I've used FastDelegate most of the time and then std::function after that.
All the links I posted should have tutorial information to get you up and running and show you how to properly pass and store member functions and/or general function pointers with ease.
Here's an example of using a FastDelegate with your example:
class A
{
public:
// [1] This creates a delegate type. Can used for any function,
// class function, static function, that takes one int
// and has a return type of an int.
typedef FastDelegate1< int, int > Delegate;
// [2] Pass the delegate into 'A' and save a copy of it.
A( const Delegate& delegate ) : _delegate( delegate ) { };
void execute()
{
// [7]
// Result should be 10!
int result = _delegate( 8 );
}
private:
// [3] Storage to save the Delegate in A.
Delegate _delegate;
};
class B
{
public:
B()
{
// [4] Create the delegate
A::Delegate bDelegate;
bDelegate.bind( this, &B::function );
// [5] Create 'A' passing in the delegate.
_aPtr = new A( bDelegate );
// [6] Test it out!! :)
// This causes `A` to execute the Delegate which calls B::function.
_aPtr->execute();
}
~B()
{
delete _aPtr;
}
int function( int n )
{
return n+2;
}
private:
A* _aPtr;
};
There is such code:
void foo(void (*fun_ptr)()){
}
class B{
public:
B(){
foo(some_fun);
}
void some_fun(){}
};
Compilation error:
error: argument of type ‘void (B::)()’ does not match ‘void (*)()’
How to point to member function in this case? I cannot change declaration of function foo, only class B!
Declare B::some_fun() as static as there is an implicit this pointer passed as an argument to member functions. Note that making B::some_fun() static prevents access to non-public non-static members of B.
This a FAQ in it's own right.
There is no other solution than to wrap the member function in a static function and somehow tell it about the object instance to invoke the method on:
struct X { void foo(); }
void take_callback(void (*fun_ptr)())
{
fun_ptr(); // invoke callback
}
//wrap the method
X* instance = 0;
void wrap_memberfun()
{
if (instance) instance->foo(); // delegate
}
int main()
{
X x;
take_callback(&X::foo); // doesn't compile
// workaround:
instance = &x;
take_callback(&wrap_memberfun);
}
some_fun() is a member function and needs an object. Make some_fun() static.
static void some_fun() {};
To invoke non-static member function you need two pointers (function and class instance), so you can't really use pointer to a non-static member where you expect pointer to a function.