Member function pointer to function object - c++

I have a class with a function pointer as a member. In a certain case I would like that pointer to point to a function object, is that not possible?
class C {
public:
C();
private:
void (*p)();
struct Functor {
void operator()() {
}
};
};
C::C() : p(Functor()) {
}
int main(int argc, char **argv) {
C c;
}
I get:
t.cpp: In constructor 'C::C()':
Line 12: error: cannot convert 'C::Functor' to 'void (*)()' in initialization

No, it is not possible. The type of Functor is not even close to the type void(*)(). You can either change the member p to be of type Functor, or what you may be looking for is std::function:
std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any callable target -- functions, lambda expressions, bind expressions, or other function objects.

No, a Functor object is not a function pointer. If you would like to initialize p as a Functor, you should declare it as such:
class C {
public:
C();
private:
struct Functor {
void operator()() {
}
} p;
};

Related

Problem converting member function pointer to std::function with CRTP

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

Passing member method of derived class as base class method pointer

Can I pass the method as a pointer to some function that accepts the base class method pointer?
Like here, function tryit accepts two parameters with class Object. There should be polymorphism, but the compiler throws an error.
#include <iostream>
using namespace std;
class Object {
};
class Derived : public Object
{
private:
public:
void printit() {
cout << "Ok" << endl;
}
};
void tryit(Object* obj, void (Object::*fn)() ) {
(obj->*fn)();
}
int main() {
Derived d;
tryit(&d, &Derived::printit);
}
Compiler says this:
main.cc: In function ‘int main()’:
main.cc:31:15: error: cannot convert ‘void (Derived::*)()’ to ‘void (Object::*)()’
31 | tryit(&d, &Derived::printit);
| ^~~~~~~~~~~~~~~~~
| |
| void (Derived::*)()
main.cc:24:25: note: initializing argument 2 of ‘void tryit(Object*, void (Object::*)())’
24 | void tryit(Object* obj, void (Object::*fn)() ) {
| ^~~~~~~~~~~~~~~~~~~~
I don't want to use virtual methods in Object class, because I want to be able to call function with various names.
This works:
typedef void (Object::*memfn)();
tryit(&d, (memfn) &Derived::printit);
But why this is not converted implicitly, why do I need to cast it manually?
Unfortunately, polymorphism doesn't work this way. Member-pointers of derived classes are not implicitly convertible to member-pointers of parent classes. Only pointers (and references) to derived class objects are implicitly convertible to pointers to parent class objects.
You can cast your pointer, and make compiler happy:
int main() {
Derived d;
tryit(&d, static_cast<void (Object::*)()>(&Derived::printit));
}
Thanks to #StoryTeller-UnslanderMonica for digging, there seems to be an explicit blessing in Standard:
https://timsong-cpp.github.io/cppwp/n4868/expr.static.cast#12
Using virtual is the legal and safe way to handle this for polymorphic types. Your claim that you don't want to use virtual because you "want to be able to call function with various names" makes no sense.
But, if you really don't want to use virtual then consider making tryit() a template function instead, eg:
template<typename T>
void tryit(T* obj, void (T::*fn)() ) {
(obj->*fn)();
}
int main() {
Derived d;
tryit(&d, &Derived::printit);
}
Alternatively:
template<typename Callable>
void tryit(Callable fn) {
fn();
}
int main() {
Derived d;
tryit([&](){ d.printit(); });
}
Or, you can use std::function without a template, eg:
void tryit(std::function<void()> fn) {
fn();
}
int main() {
Derived d;
tryit([&](){ d.printit(); });
}
But why this is not converted implicitly, why do I need to cast it manually?
Because it's one of those conversions where you have to tell the compiler you posses extra knowledge that guarantees it's safe. Take object pointers for instance:
struct A { int x; };
struct B : A { char c; };
A *pa = new B();
auto pb = static_cast<B*>(pa);
Converting a B* to an A* is implicit. It's an unambiguous base class. The compiler knows there is an A object in that B and can just go ahead with it. But the converse is not true, you must cast it (employing your extra knowledge) to let it know that that A* is really pointing at a B*.
Pointers to members are the same in a way.
int B::* pmb = &A::x;
auto pma = static_cast<char A::*>(&B::c);
pa->*pma = 'c';
Obtaining a pointer to a member of B from a pointer to a member of A is an implicit conversion. The same knowledge about B containing an A (and therefore the member x) is available to the compiler. But it cannot assume the converse willy-nilly. What if the object pointer pa is not really pointing at a B? Accessing that "member of B" would be disastrous then.
By the same reasoning as before, you need a cast to let the compiler know you have extra knowledge about the actual derived object type.

How std::bind(&T::memberFunc, this) can always bind to std::function<void(void)> regardless of what T is?

As far as I know, the member function pointer only can be assigned to the pointer to member function type, and converted to any other except this will violate the standard, right?
And when calling std::bind(&T::memberFunc, this), it should return a dependent type which depend on T.(in std of VC++ version, it's a class template called _Binder).
So the question becomes to why one std::funcion can cover all _Binder(VC++ version) types.
class A
{
public:
void func(){}
};
class B
{
public:
void func(){}
};
std::function<void(void)> f[2];
A a;
B b;
f[0] = std::bind(&A::func, &a);
f[1] = std::bind(&B::func, &b);
And I can't picture what type of the member of std::funcion which stored the function would be like, unless I am wrong from the first beginning.
This question only covered the member function need to be called with it's instance.
But mine is about why one std::function type can hold all T types.
In short what is happening is that std::bind(&A::func, &a) returns an object of a class similar to
class InternalClass
{
A* a_; // Will be initialized to &a
public:
void operator()(void)
{
a_->func();
}
};
[Note that this is highly simplified]
The callable operator() function is what is matches the void(void) signature of the std::function<void(void)>.
I think the implementation would probably like this:
template</*...*/>
class std::bind</*...*/>
{
public:
std::bind(callable_t call, param_t p)
{
_func = [call, p]()/* using lambda to capture all data for future calling */
{
p->call();
};
}
operator std::function<void(void)>()
{
return _func;
}
private:
std::function<void(void)> _func;
};
And lambda is the key.

Why do function pointers break substitutability and std::function doesn't?

We have an usual class hierarchy:
class B
{
public:
int x;
B() : x(0) {}
virtual ~B() {}
};
class D : public B
{
public:
int y;
D() : y(0) {}
};
And a function that takes one argument - reference to a base class object.
void b_set(B& b)
{
b.x = 5;
}
Then, I want to create function pointer of type void (D&) and store b_set in it. This should be valid operation, as all objects legally passed to function pointer call must be also of type B. Yet it isn't allowed.
typedef void (*fp_d_mutator)(D&);
void fp_test(D& obj)
{
fp_d_mutator fun = b_set; //invalid conversion from 'void (*)(B&)' to 'fp_d_mutator {aka void (*)(D&)}
fun(obj);
}
#include <functional>
typedef std::function<void (D&)> stdfun_d_mutator;
void stdfun_test(D& obj)
{
stdfun_d_mutator fun = b_set; //works
fun(obj);
}
So...
How is that invalid conversion?
Why is that invalid conversion?
What could break if this was allowed?
How std::function avoids the problem in the first place?
A function that takes an argument of type B& is not a function that takes an argument of type D&. While D& is convertible to B&, they are not the same type. If you could store a pointer to a function that takes B& as a pointer to D&, how would the compiler know when to convert the argument? (Note that the conversion sometimes requires adjusting a pointer)
The difference in std::function is that the calling signature (here D&) is part of the function object's type, and the called signature (here B&) is part of the internal storage. So when you apply the function objects' operator() the code that implements operator()(D&) takes care of the conversion.

function pointer from one class to member function of any class

I'm having difficulties defining a function pointer that can point to any member function (not just member functions for the specified class).
For instance, C++ forces me to specify the class that a function pointer to a member function would point to:
typedef void (Foo::*MyFunctionPointerTypeName)(int);
but what if the class member function that this function pointer is going to point to isn't in Foo? How then would I write this, or what alternative approach could I use?
Update: For anyone looking for a quick answer on how to accomplish this with a C++11 std::function (as tutorials on the subject seem to assume alot of the reader):
Definition (from within Foo):
std::function<void(int)> _fun;
Binding (from any class):
objFoo->_fun = std::bind(&SomeOtherClass::memberFunction,
this, std::placeholders::_1);
Calling it (from within Foo)
if(_fun != nullptr) _fun(42);
If your function has no parameters, you can remove std::placeholders::_1. And if your function has two parameters you'll need to also add std::placeholders::_2 as a parameter to std::bind. Similarly for three parameters, four parameters, etc.
You cannot write a member pointer that could point to a member of any class. Remember: one of the arguments of a member pointer is the class instance itself. And pointers are typed, so the type of its arguments is very much a part of the pointer's type.
You can use std::function however, which can store all sorts of callables. How you would actually call it (ie: what parameters you give it) depends on your needs, as you haven't explained what you're trying to do.
Use inheritance:
#include <iostream>
struct Foo {};
struct Bar : public Foo
{
int F0()
{
return 0;
}
};
struct Baz : public Foo
{
int F1()
{
return 1;
}
};
int main(int argc, char **argv)
{
int (Bar::*pF0)() = &Bar::F0;
int (Baz::*pF1)() = &Baz::F1;
int (Foo::*pointer1)() = static_cast<int (Foo::*)()>(pF0);
int (Foo::*pointer2)() = static_cast<int (Foo::*)()>(pF1);
Bar r;
Baz z;
// Pointer to Foo member function calling Bar member function
std::cout << (r.*pointer1)() << '\n';
// Pointer to Foo member function calling Baz member function
std::cout << (z.*pointer2)() << '\n';
return 0;
}
Output:
0
1
Hope it helps.