How to define, assign and use an Array of Pointer-to-Method? - c++

In my project I have an hierarchy of classes. An object of type C_t contains (dynamically allocated) array of A_t objects and a B_t object.
I want to invoke an A_t method a_fn() from a B_t's method b_fn(). I can do that in several ways, and several levels of indirection.
B maintains a pointer to its containing object C. Then I use this pointer to directly refer to A[] and its method.
Next, I defined pointers to A_t and initialized them with the references to A[]s, and use these pointers to indirectly invoke A[]'s method.
Assume that in the actual project the hierarchy is deeper and that the object names are descriptive and long, this style becomes long and convoluted statements.
I want to maintain an array of pointers to A[]'s method a_fn() and use these array members to invoke the methods. I.e., how to make the (commented out) statements that would print x = 46 and x = 47 work?
#include <iostream>
using namespace std;
struct A_t;
struct B_t;
struct C_t;
// Top level class
struct C_t {
A_t *A[2];
B_t *B;
C_t();
};
struct A_t {
void a_fn(int x) { cout << "x = " << x << endl; };
};
// Define func-ptr to A_t's method
typedef void (A_t::*p_fn_t)(int);
struct B_t {
C_t* p_C; // ptr to containing object
A_t** p_A[2]; // array of ptrs-to-array-of-As
p_fn_t p_fn; // ptr to A_t's method
p_fn_t pa_fn[2]; // array of ptr to A_t's method
void b_fn() {
p_C->A[0]->a_fn(10); // Cptr-direct
(p_C->A[0]->*p_fn)(11); // Cptr-indirect
(*p_A)[1]->a_fn(22); // Aptr-direct
((*p_A)[1]->*p_fn)(23); // Aptr-indirect
((*p_A)[0]->*(pa_fn[0]))(34); // Aptr-fptr-indirect
((*p_A)[1]->*(pa_fn[1]))(35); // Aptr-fptr-indirect
//pa_fn[0](46); // <<-- HOW TO DO THIS???
//pa_fn[1](47); // <<-- HOW TO DO THIS???
};
B_t(C_t *C) : p_C(C) {
p_fn = &A_t::a_fn; // init fptr-to-A's-method
p_A[0] = &(p_C->A[0]); // init ptr-to-A[0]
p_A[1] = &(p_C->A[1]); // init ptr-to-A[1]
// The following assignments need to change in order to get
// what I am looking for. Something along the line of
// pa_fn[0] = &(A[0]->(A_t::a_fn));
pa_fn[0] = &A_t::a_fn; // init fptr-to-A's-method
pa_fn[1] = &A_t::a_fn; // init fptr-to-A's-method
};
};
C_t::C_t() {
// Instantiate As and B and init B with C's own ptr
A[0] = new A_t;
A[1] = new A_t;
B = new B_t(this);
};
int main(int argc, char *argv[])
{
C_t C;
C.B->b_fn(); // Invoke B's method
return 0;
}
This program's output:
x = 10
x = 11
x = 22
x = 23
x = 34
x = 35
Update: In the actual project there is another level of hierarchy, so A_t contains AA_t and B_t contains BB_t object pointers. So, the method invocation will look like:
((*p_A)[0]->AA->*(pa_fn[0]))(34);
and given long names:
((*p_A_object)[0]->AA_sub_object->*(pa_method_fn[0]))(34);
It is easy to see how this can become long and hard to read.

As Toby pointed out you can't do it with plain pointers, but is possible with
function+bind:
std::function<void(int)> f_fn = std::bind(&A_t::a_fn, p_A[0]) ;

To make this work you need an instance of A_t to call one of its functions, not only a function pointer. E.g. like this:
#include <iostream>
struct foo { void bar(int x) {std::cout << "moo " << x << std::endl; } };
typedef void (foo::*p_fn_t)(int);
void test(foo f,p_fn_t fn){ (f.*fn)(3); }
int main() {
foo f;
p_fn_t fn = &foo::bar;
test(f,fn);
}
The syntax is easy to get wrong. It is .* or ->* to invoke a function via a member function pointer.
PS: it seems like A_ts function in your example could be as well static, which would explain why you didnt realize that you need an instance. In that case you might consider to simply use free functions instead of putting them into a struct. (Actually I dont know how to invoke a static function via a member function pointer)

Related

Class constructor that takes a reference to a different object and I would like to not copy the object

I'm a student learning c++.
I have two objects ("City" and "Parser") and I'd like one object("Parser") to modify to other one("City").
The only "problem" is that I have to send the object("City") in the other one's constructor (The code is showing what I mean).
class City {
public:
City()
: peopleCount { 0 }
{};
int peopleCount;
};
class Parser {
public:
Parser(const char *filename, City &c)
: _filename { filename },
_c { c }
{};
void fillCity() { _c.peopleCount = 3; };
const char *_filename;
City _c;
};
int main(int argc, char *argv[])
{
City c;
Parser p(argv[1], c);
p.fillCity();
std::cout << c.peopleCount << std::endl; // I would like my output to be "3"
return 0;
}
I could do that in C by sending a raw pointer in the constructor.
But since I discover this langage, everyone is saying that raw pointer must be avoided.
I checked smart pointers but they would "delete" my variable (my variable is from the Stack, for that reason I don't want to delete it).
I do not want to copy the "City" in the "Parser" (because copying objects can be avoided ?).
I am aware that I could send a reference of a City object to the member function "fillCity" but I would like to know if the one object can hold another object without copying it.
Is there another way to do that without using raw pointer ?
Thanks in advance.
If you want to share objects while having the life time of these objects under control, you can use shared_ptr. Thereby, the shared object will be destructed once all references to it have been released (i.e. the last shared_ptr-wrapper got destructed):
class City {
public:
City()
: peopleCount(0)
{};
int peopleCount;
};
class Parser {
public:
Parser(const char *filename, std::shared_ptr<City> c)
: _filename (filename),
_c (c) {};
void fillCity() { _c->peopleCount = 3; };
const char *_filename;
std::shared_ptr<City> _c;
};
int main(int argc, char *argv[])
{
std::shared_ptr<City> c = std::make_shared<City>();
Parser p("somefilename", c);
p.fillCity();
std::cout << c->peopleCount << std::endl;
return 0;
}
In the Parser constructor, you pass the City argument by reference. But then you copy the object to store it in _c.
You should make _c a reference as well.
Another option (after Some Programmer Dude's correct answer) is to pass c in as a reference to some of P's member functions, e.g.:
class Parser {
public:
Parser(const char *filename)
: _filename { filename }
{};
void fillCity(City &c) { c.peopleCount = 3; };
const char *_filename;
};
Used like:
int main(int argc, char *argv[])
{
City c;
Parser p(argv[1]);
p.fillCity(c);
std::cout << c.peopleCount << std::endl; // I would like my output to be "3"
return 0;
}
This may or may not be how you want it - but if you just have one or a small number of functions this is quite convinient.
On another point - I would not say passing-by-pointer is so bad, for example you can at least default construct with a pointer (default value being nullptr) and then later pass in the C object. The only "issue" is that you need to be careful that C exists for the lifetime of P or that you tell P if/when C dissapears... not really rocket sceince :) and it can be quite convinient.

multi inheriting a struct from struct and template struct, ordering matters when accessing base non-template struct data

#include <stdlib.h>
#include <string>
#include <atomic>
struct base_C_event {
const char* ev;
const char* da;
};
template <class T>
struct ref_counter {
private:
std::atomic<std::ptrdiff_t> _counter;
};
struct derived_event : ref_counter<derived_event>, base_C_event {
derived_event() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct derived_event2 : base_C_event, ref_counter<derived_event2> {
derived_event2() : event_type(), event_data() {
ev = event_type.c_str();
da = event_data.c_str();
}
std::string event_type;
std::string event_data;
};
struct some_cool_event {
int type;
void* payload;
};
void OnEvent(const some_cool_event* event) {
auto e = static_cast<base_C_event*>(event->payload); //...and then shows itself here
printf("%s - %s\n", e->ev, e->da);
}
int main() {
derived_event evt;
evt.event_type = "type";
evt.event_data = "Hello World";
derived_event2 evt2;
evt2.event_type = "hi";
evt2.event_data = "there";
some_cool_event my_event;
my_event.type = 1;
my_event.payload = &evt; //Problem starts here...
OnEvent(&my_event);
my_event.type = 2;
my_event.payload = &evt2;
OnEvent(&my_event);
return 0;
}
output: (compiled with g++)
(null) - type
type - Hello World
now, in my real environment (XCode) the ordering of inheritance for derived_event causes a BADACCESS exception; with g++ it just produces (null) as shown in the output.
however, the ordering for derived_event2 works just fine.
The way i understand the standard, the order of multiple inheritance effects the order of constructors and destructors, and also the layout of the memory. Can anyone explain what is happening here?
EDIT:
I have actually figured this out. The line that sets the event object to the void* payload, and then the ensuing static_cast<> back to the base type... seems to invalidate the first pointer (ev) because the struct becomes just a memory layout at that point, so the pointers are getting set to the first two pointer size chunks... in this case std::atomic<std::ptrdiff_t> and then the base_C_event. so the cast is grabbing the data for the std::atomic and using that as the pointer address for ev, and what was originally ev in the derived object is now what da points at.
I unfortunately in my real scenario can't use composition for the base_C_event in my derived_event and send that. that's why the refcounting is there, so i have to send the derived object so that later on in a callback i can decrement the refcount.
Is there a way to prevent this from happening?
Hm, I think I see where the problem lies:
struct D : B<D>, A { };
This way you inherit both a B<D> and a A instance. Effectively, this ressembles something like this:
struct D
{
B<D> implicitly_inherited_B_D;
A implicitly_inherited_A;
};
You now do the following:
D* d = new D();
void* v = d;
A* a = static_cast<A*>(v);
Problem is: v now points to the D instance, which shares its address with the inherited B<D> instance. But you cast the pointer back to A*, however, Ds A has an offset. So what you do corresponds to:
D* d = new D();
void* v = &d->implicitly_inherited_B_D;
A* a = static_cast<A*>(v);
// or equivalent:
A* aa = reinterpret_cast<A*>(&d->implicitly_inherited_B_D);
This is bound to fail...
If you want to cast back to A*, you need to make sure that your pointer actually points to the inherited A within D - which is quite easy:
D* d = new D();
void* v = static_cast<A*>(d);
// now this will work fine (v points to D's A part):
A* a = static_cast<A*>(v);
D* dd = static_cast<D*>(a); // even this one, original object was constructed as D
For comparison:
D* d = new D();
A* a = d;
D* ds = static_cast<D*>(a);
D* dr = reinterpret_cast<D*>(a); // actually undefined behaviour!!!
std::cout << d << std::endl << a << std::endl << ds << std::endl << dr << std::endl;
Assuming address of d is 0x10001000 and A within D has an offset of 8(sizeof(B<D> + possibly fill bytes for alignment), you'd see an output like this:
10001000
10001008
10001000
10001008
Note that the last line originates from the D* pointer received via reinterpret_cast!
Final note: Be aware that members can be rearranged - members declared first preceding members declared afterwards only is guaranteed for members within the same accessibility class (public/protected/private), between these sections, compiler is allowed to re-arrange. So in general you only can be safe if you go back from void* the same way you used for getting there:
void* v = d; // -> need to go back via static_cast<D*>!
A* a = static_cast<A*>(v); // requires v = static_cast<A*>(d);
B<D>* d = static_cast<B<D>*>(v); // requires v = static_cast<B<D>*>(d);
Anything else is undefined behaviour (be aware that the matter gets even worse as soon as virtual classes are involved, as then additionally there are the vtable pointers...).
If you cast a pointer to void * then always do the exact inverse cast when casting back to actual type.
So if you have :
D *d = new D;
void *v = d; // Here D* is casted to void *
When you get back the pointer, use the inverse cast. The following example are correct:
D *d2 = static_cast<D *>(v);
A *a2 = static_cast<D *>(v);
B<D> *b2 = static_cast<D *>(v);
Even better, if you can, try to avoid using void *. It can easily lead to hard-to-find bugs and this is even worst when using multiple inheritance.
If you have to use void *, then try do to it as locally as possible in the code so that ideally the conversion is done exactly at one place in the code for each direction.
class VoidMember
{
public:
void set(D *d) { v = d; }
D *get() { return static_cast<D *>(v);
private:
// In reality, you would not store a void like that but assume this is stored in
// a library / API that use `void *`
void *v;
};
While casting to other types might sometime works, it should be avoided as it make the code more fragile if code is refactored at some point like reordering base classes.

Having the same member function have different definitions for different class instances

Is it possible for the same member function to have different definitions for different objects of that class?
IMPORTANT NOTE: I cannot use a callback like in this solution. (reason explained below example)
Lets say we have this object:
struct object
{
int n;
int m;
void f();
};
Is it possible to have something like:
object a,b;
// and here to define the functions
a.f() {std::cout << n+m;}
b.f() {std::cout << n-m;}
The reason i cannot use a callback is because the function i want to define will be recursive and will overflow. What i am trying to do with this method is to create an immitation of the stack (but all the variables are stored on heap as a double chained list) and so i will call a void (void) function that has no local variables thus increasing the stack depth the function can achieve. Also important to mention is that i want to make a header file with this idea. For further context explination, this is how it should work:
MyHeader.h
template <typename PARAM_TYPE> class HEAP_FUNCTION
{
private:
struct THIS_CALL // ! THIS HAS NOTHING TO DO WITH THE __thiscall CALLING CONVENTION !
{
PARAM_TYPE* PARAM;
THIS_CALL* next_call;
THIS_CALL* prev_call;
};
THIS_CALL* FIRST_CALL;
THIS_CALL* CURRENT_CALL;
public:
HEAP_FUNCTION(PARAM_TYPE* FirstCall)
{
FIRST_CALL = new THIS_CALL;
CURRENT_CALL = FIRST_CALL;
FIRST_CALL->PARAM = *FirstCall;
}
HEAP_FUNCTION(PARAM_TYPE FirstCall)
{
FIRST_CALL = new THIS_CALL;
CURRENT_CALL = FIRST_CALL;
FIRST_CALL->PARAM = FirstCall;
}
~HEAP_FUNCTION()
{
delete FIRST_CALL;
}
void call(void);
};
Source.cpp
// This is the ilustration of the recursive method for calculating
// the 1+2+3+...+n sum.
// The "normal" definition for this function would be:
//
// unsigned long long sum(unsigned long long n)
// {
// if (n == 0) return 0;
// return n + sum(n-1);
// }
//
// The function presented bellow is the equivalent.
struct Param
{
unsigned long long n;
unsigned long long return_value;
}
int main()
{
Param start_value;
start_value.n = 10; // we will calculate 1+2+...+10
HEAP_FUNCTION<Param> Gauss(&start_value);
// We imagine this is where i define call().
// The code written in this definiton works correctly.
Gauss.call()
{
// Test if the function needs to stop further calls.
if(CURRENT_CALL->PARAM->n == 0)
{
CURRENT_CALL->PARAM->return_value = 0;
return;
}
// Prepare the parameters for the next function call.
CURRENT_CALL->next_call = new THIS_CALL;
CURRENT_cALL->next_call->PARAM = new PARAM_TYPE;
CURRENT_CALL->next_call->prev_call = CURRENT_CALL;
CURRENT_CALL->next_call->PARAM->n = CURRENT_CALL->PARAM->n - 1;
// Call the next instance of the function.
CURRENT_CALL = CURRENT_CALL->next_call;
call();
CURRENT_CALL = CURRENT_CALL->prev_call;
// Collect the return value of the callee.
CURRENT_CALL->PARAM->return_value = CURRENT_CALL->PARAM->n + CURRENT_CALL->next_call->PARAM->return_value;
// Delete the space used by the callee.
delete CURRENT_CALL->next_call;
}
// This is the actual call of the function.
Gauss.call();
// The return value is found in the start_value struct.
std::cout << start_value.return_value << std::endl;
return 0;
}
IMPORTANT NOTE: Derivering the entire class will result in a single call() definition for funtions like sum(a, b) and dif(a, b) since they will use the same PARAM struct. (Even though they are not recursive, and the probability of someone using this is very small, this method is good in a bigger program when some of your functions will have a lot of parameters and just placing them on the heap will result in more stack space)
Don't think I understood the question properly, but did you consider function overloading?

Increment value from void pointer

I'm trying to modify some variables [not necessary from the same class/struct] from keyboard's shortcuts, something like that:
A foo struct containing variables:
struct Foo {
int a;
float b;
};
struct Foo2 {
int c;
};
And a main like:
int main() {
Foo f;
Foo2 f2
void* p = &(f.a); //it could be &(f2.c)
if ('A' key activated) {
*p += 1;
}
}
Currently, I'm stucked at this point:
error: invalid operands to binary expression ('void' and 'int')
The only way to make it work is to change:
*p += 1;
By:
*(int*)p += 1;
Which is not a good solution, because I should not know the type pointed by p. Is there a way to do that?
Converting the pointer to void* lost the type information and the compiler will not know how to increment. Why don't you make a pointer to Foo instead?
int main() {
Foo f;
Foo* p = &f;
if ('A' key activated) {
p->a += 1;
}
}
Also keep in mind that incrementing a float is not a good idea!
For the quesion in the comment of this answer:
struct FooBar
{
int *a;
float *b;
};
int main() {
Foo f;
Bar b;
FooBar fb{&f.a, &b.b};
if ('A' key activated) {
*(fb.a) += 1;
}
}
Note that this solution is rather C-style. Look at lethal-guitar's answer for a more C++-style solution.
Edit: At first I didn't realize that you want to have different types per entry. Based on the task of handling keyboard shortcuts, you could use a polymorphic class, and put instances of it into a std::map:
class KeyHandler {
public:
virtual void onKeyStroke() = 0;
};
class MyHandler : public KeyHandler {
public:
MyHandler(int& value) : myValue(value) {}
virtual void onKeyStroke() {
myValue_ += 1;
}
private:
int& myValue_; // Other subclasses could have other data
};
// Now place instances of different Handlers into a std::map
typedef std::shared_ptr<KeyHandler> PKeyHandler;
std::map<char, PKeyHandler> bindings;
bindings['A'] = PKeyHandler(new IncrementIntHandler(&someInt));
bindings['B'] = PKeyHandler(new IncrementFloatHandler(&someFloat));
// The actual input handler then just invokes
// the correct handler for a key stroke.
bindings[keyCode]->onKeyStroke();
That way, you can define a handler class for every action you want to support, and implement the corresponding logic into these classes. You could make the base class' implementation just do nothing to handle non-mapped keys, etc.
Sure, use an int pointer instead:
int * p = &f.a;
if ( /* condition */ ) { ++*p; }

raw function pointer from a bound method

I need to bind a method into a function-callback, except this snippet is not legal as discussed in demote-boostfunction-to-a-plain-function-pointer.
What's the simplest way to get this behavior?
struct C {
void m(int x) {
(void) x;
_asm int 3;
}};
typedef void (*cb_t)(int);
int main() {
C c;
boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1);
cb_t raw_cb = *cb.target<cb_t>(); //null dereference
raw_cb(1);
return 0;
}
You can make your own class to do the same thing as the boost bind function. All the class has to do is accept the function type and a pointer to the object that contains the function. For example, this is a void return and void param delegate:
template<typename owner>
class VoidDelegate : public IDelegate
{
public:
VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
{
mFunction = aFunc;
mOwner = aOwner;
}
~VoidDelegate(void)
{}
void Invoke(void)
{
if(mFunction != 0)
{
(mOwner->*mFunction)();
}
}
private:
void (owner::*mFunction)(void);
owner* mOwner;
};
Usage:
class C
{
void CallMe(void)
{
std::cout << "called";
}
};
int main(int aArgc, char** aArgv)
{
C c;
VoidDelegate<C> delegate(&C::CallMe, &c);
delegate.Invoke();
}
Now, since VoidDelegate<C> is a type, having a collection of these might not be practical, because what if the list was to contain functions of class B too? It couldn't.
This is where polymorphism comes into play. You can create an interface IDelegate, which has a function Invoke:
class IDelegate
{
virtual ~IDelegate(void) { }
virtual void Invoke(void) = 0;
}
If VoidDelegate<T> implements IDelegate you could have a collection of IDelegates and therefore have callbacks to methods in different class types.
Either you can shove that bound parameter into a global variable and create a static function that can pick up the value and call the function on it, or you're going to have to generate per-instance functions on the fly - this will involve some kind of on the fly code-gen to generate a stub function on the heap that has a static local variable set to the value you want, and then calls the function on it.
The first way is simple and easy to understand, but not at all thread-safe or reentrant. The second version is messy and difficult, but thread-safe and reentrant if done right.
Edit: I just found out that ATL uses the code generation technique to do exactly this - they generate thunks on the fly that set up the this pointer and other data and then jump to the call back function. Here's a CodeProject article that explains how that works and might give you an idea of how to do it yourself. Particularly look at the last sample (Program 77).
Note that since the article was written DEP has come into existance and you'll need to use VirtualAlloc with PAGE_EXECUTE_READWRITE to get a chunk of memory where you can allocate your thunks and execute them.
#include <iostream>
typedef void(*callback_t)(int);
template< typename Class, void (Class::*Method_Pointer)(void) >
void wrapper( int class_pointer )
{
Class * const self = (Class*)(void*)class_pointer;
(self->*Method_Pointer)();
}
class A
{
public:
int m_i;
void callback( )
{ std::cout << "callback: " << m_i << std::endl; }
};
int main()
{
A a = { 10 };
callback_t cb = &wrapper<A,&A::callback>;
cb( (int)(void*)&a);
}
i have it working right now by turning C into a singleton, factoring C::m into C::m_Impl, and declaring static C::m(int) which forwards to the singleton instance. talk about a hack.