0

My question is: Is there a way to declare static member pointers to their own classes automatically?

I have a C++ state machine, in which classes have static pointers to their own classes. This means I can bind a given object to the pointer in its class uniquely. In other words, from each class, only 1 instance can be bound to the static pointers, which pointers then can be used to select from the pool of instances the one that is currently bound.

class A {
public:
   static A *ptr;
   void bind() { ptr = this; }
}

class B {
public:
   static B *ptr;
   void bind() { ptr = this; }
}

To me this seems like there has to be some way to abstract this. The process in each class is basically the same: a static pointer to the class and a bind function to assign this to said pointer. (I'm aware of the dangers regarding the lifetimes of each particular bound object, consider this taken care of.)

As far as I know, these type of abstractions are usually performed with inheritance, however I can't seem to find a way to abstract out the type of ptr in a hierarchy, or using template classes.

The optimal solution would be one that doesn't need any information from the programmer regarding the type of ptr in any of the classes, since it seems to be available information at compile time.

Can this be done? Can it be avoided to explicitly declare ptr in each class and automate the process?

This is the closes I got to a solution, but did not succeed: C++ - Are there ways to get current class type with invariant syntax?

Thank you in advance!

  • 3
    That seems to be big nonsense, and should not be done at all. `static` shares that for All instances. – πάντα ῥεῖ Aug 10 '22 at 21:54
  • @πάντα ῥεῖ I'm sorry, I'm not sure what you mean. Let me elaborate a little. What I'm planning is that for example class `A` will have numerous objects (let them be `a`, `b` and `c`) from which I want to use only 1 at a time. If `a` calls its `bind` function, then I can simply derefer `A::ptr` to get `a` (given it is still in scope). The situation is the same with class `B` and some others as well. This seems to be abstractable to me, in which I have been unsuccessful. Is this such a bad idea? – Daniel Varga Aug 10 '22 at 22:08
  • 1
    I am struggling to understand what you are trying to do. This inhibits my ability to render meaningful aid. – user4581301 Aug 10 '22 at 22:09
  • @user4581301 I'm working on an OpenGL-based graphical library. To draw an object for example, I have to choose a shader from a pool of `Shader` objects, a texture from a pool of `Texture` objects etc. I can bind the `Shader` and `Texture` object I want to use and then the object can just derefer `Shader::ptr` and `Texture::ptr` to get the bound shader and the bound texture. What I'm trying to do is to abstract away having to declare `ptr` explicitly in `Shader` and in `Texture`. Is it clearer? – Daniel Varga Aug 10 '22 at 22:25
  • 1
    This seems like a bad idea. It's error-prone. IMO better to just make local pointers/references when you need them. If your items come from a container with an index then keep track of that if you wish, at least when it all goes horribly wrong the incorrect index will be easier to track down than a pointer. – Retired Ninja Aug 10 '22 at 22:43
  • @DanielVarga that's a horribly bad idea, yes. The closest thing I can think of is some class type reference, like available in Delphi, Smalltalk, Ada or such, but not with c++. c++ meta programming is restricted to compile time template expressions. There are no reflection utilities available with standard c++. – πάντα ῥεῖ Aug 10 '22 at 22:53
  • @πάντα ῥεῖ I'm not trying to be stubborn here, but I just don't get how this is a _horrible_ idea. The answer by Sam Varshavchik works exactly like I want it to, in compile time, what's wrong with that? I get that it might be error-prone according to Retired Ninja, but not how this is _horrible_. That said, I'm not adamant on this approach, in fact, I've been considering simply storing these objects in an STL container myself, I just wanted to explore this approach as well. My main reason for this approach is it being a nice reflection on OpenGL itself being a state machine. – Daniel Varga Aug 10 '22 at 23:09
  • @DanielVarga it works as long you have everything available at compile time with c++. That's a narrow field. – πάντα ῥεῖ Aug 10 '22 at 23:54

1 Answers1

1

The only thing I can think of would be a CRTP-based approach, something like:

template<typename T> struct current_instance {

    static T *ptr;

    void bind() { ptr = static_cast<T *>(this); }
};

// ...

template<typename T> T *current_instance<T>::ptr;

//--------------------------------------------------------------

class A : current_instance<A> {
  // ...
};

class B : current_instance<B> {
  // ...
};
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Thank you @Sam Varshavchik for the quick answer! This seems to work just like I'd like it to. I have a theoretical question though if I may: in an `A` object (call it `a`), in the `bind` function, `this` refers to the`current_instance` object, currently a subset of `a` which is then cast to refer to `a` itself. How exactly is this possible? Is it guaranteed that the memory addresses are the same? It would not be possible if there were multiple base classes. Or is `static_cast` so smart that it can perform `base* -> derived*` conversions? What conditions are required for this to be possible? – Daniel Varga Aug 10 '22 at 22:51
  • `static_cast` is just that smart, casting base to derived, as long as there's no multiple or virtual inheritance. – Sam Varshavchik Aug 10 '22 at 23:09