C++ Get class type inside static function
Asked Answered
P

7

9

Inside of a static member function I need to get the type.

class MyClass
{
     public:
         static void myStaticFunc();
     ...
};

And then in the implementation I want to have:

void MyClass::myStaticFunc()
{
     // Get MyClass as a type so I can cast using it
     (get_type_from_static_function()*)someOtherVariable;
}

Is this even possible? Normally I would use something from typeinfo on an object but I don't have this to work with.

I do not want to just use (MyClass*) because this is going inside of a macro and I'd like to keep it as simple as possible so that it can be called without a class name.

If it helps I am using QT but I couldn't find any macros to get the current class. It doesn't necessarily need to be programmatic - it can be a macro.

Cheers!

EDIT: Here is the actual macro function:

#define RPC_FUNCTION(funcName) \
static void rpc_##funcName(void* oOwner, RpcManager::RpcParamsContainer params){ ((__class__*)oOwner)->funcName(params); }; \
void funcName(RpcManager::RpcParamsContainer params);

I then call RPC_FUNCTION(foo) in a class declaration. I want __class__ to be whatever class declaration I am in. I'm well aware I can just add className after funcName but I want to keep this as simple as possible when actually using it. My RPC manager calls rpc_foo and passes a pointer to an object of the class I declared it in. Essentially I need to know how to determine the actual class of that void* parameter.

Professed answered 7/11, 2011 at 1:5 Comment(0)
P
1

I believe that what you're asking for at heart is simply not possible: C++ is a statically typed language, which means that all type information must be available at compile time (runtime polymorphism notwithstanding). That is, when you say,

T x;

then the type T must be known at compile time. There is no such thing as "T_from_user() x;", whereby the actual type of a variable is determined at runtime. The language just isn't designed that way.

Usually if you're asking such a question that's an indicator that you're going about a problem the wrong way, though. Typical solutions for polymorphic situations involve class inheritance and virtual functions, or other sorts of lookup tables, or really any number of different approaches. Your request for a preprocessor macro also indicates that something is off. Any programming language has its idioms, and veering too far from those is usually a bad idea.

Pontic answered 7/11, 2011 at 1:16 Comment(6)
Sort of, I'm more using it for casting an object (that is currently a void*) inside of a macro. Like this: static void myFunction(void* owner) { // I need to get MyClass so that I can cast it without explicitly writing it. (MyClass*)owner->myMemberFunction(); }Professed
Why don't you post your actual problem in the question, and we can take a look? The more abstract the better; always assume that any decisions you already made towards solving the problem may have gone in the wrong direction.Pontic
@cleversoap: You could just endow your classes with a typedef typedef Myclass SelfType; and always put reinterpret_cast<SelfType*>(owner) in your macro.Pontic
Why reinterpret_cast? A simple static_cast will suffice.Staats
That typedef seems like the best solution. I just call an init macro in any class declarations. Thanks for all your help!Professed
@Xeo: indeed, thanks! static_cast<SelfType*>(owner) it should be... cleversoap: Don't litter macros everywhere if you can get the same effect with essentially the same amount of writing proper C++ code. Macros is eevil :-SPontic
R
3

In Visual Studio 2012 you can use that trick, but it will not work in gcc, at least for now.

        template<typename base_t>
        static auto GetFunctionBaseType(void(base_t::*)())->base_t;

        struct TBase
        {
            template<typename T> void GetBaseType();
            typedef decltype(GetFunctionBaseType(&GetBaseType<void>)) this_t;

            static void rpc_func1(void * ptr)
            {
                ((this_t*)ptr)->func1();
            }
        };
Redress answered 9/10, 2014 at 9:25 Comment(0)
P
1

I believe that what you're asking for at heart is simply not possible: C++ is a statically typed language, which means that all type information must be available at compile time (runtime polymorphism notwithstanding). That is, when you say,

T x;

then the type T must be known at compile time. There is no such thing as "T_from_user() x;", whereby the actual type of a variable is determined at runtime. The language just isn't designed that way.

Usually if you're asking such a question that's an indicator that you're going about a problem the wrong way, though. Typical solutions for polymorphic situations involve class inheritance and virtual functions, or other sorts of lookup tables, or really any number of different approaches. Your request for a preprocessor macro also indicates that something is off. Any programming language has its idioms, and veering too far from those is usually a bad idea.

Pontic answered 7/11, 2011 at 1:16 Comment(6)
Sort of, I'm more using it for casting an object (that is currently a void*) inside of a macro. Like this: static void myFunction(void* owner) { // I need to get MyClass so that I can cast it without explicitly writing it. (MyClass*)owner->myMemberFunction(); }Professed
Why don't you post your actual problem in the question, and we can take a look? The more abstract the better; always assume that any decisions you already made towards solving the problem may have gone in the wrong direction.Pontic
@cleversoap: You could just endow your classes with a typedef typedef Myclass SelfType; and always put reinterpret_cast<SelfType*>(owner) in your macro.Pontic
Why reinterpret_cast? A simple static_cast will suffice.Staats
That typedef seems like the best solution. I just call an init macro in any class declarations. Thanks for all your help!Professed
@Xeo: indeed, thanks! static_cast<SelfType*>(owner) it should be... cleversoap: Don't litter macros everywhere if you can get the same effect with essentially the same amount of writing proper C++ code. Macros is eevil :-SPontic
R
0

What you want to do is called Reflection. It was implemented in .NET (I don't know, maybe in Java too) and is going to be implemented in future standards of C++.

Revolve answered 7/11, 2011 at 1:18 Comment(1)
I believe that the problem is static typing, not lack of reflection. Reflection is something slightly different.Pontic
S
0

It seems you have a few unrelated classes that have a number of methods in common (the ones that can be sent as the funcName argument in your example).

Instead of having these unrelated classes, consider a polymorphic approach. For example, let's say the functions that you support are func1 and func2, then you can work this out in this way:

class BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) = 0;
    virtual void func2(RpcManager::RpcParamsContainer args) = 0;
};

class MyClass1 : public BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) { /* func1 implementation here */ }
    virtual void func2(RpcManager::RpcParamsContainer args) { /* func2 implementation here */ }
};

class MyClass2 : public BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) { /* func1 implementation here */ }
    virtual void func2(RpcManager::RpcParamsContainer args) { /* func2 implementation here */ }
};

With the above design your can pass a BaseClass* around, and you can call func1 or func2 without having to do any casts, and the compiler will find the correct version to invoke. For example, in your macro you could do something like this:

#define RPC_FUNCTION(funcName) static void rpc_##funcName(BaseClass* oOwner, RpcManager::RpcParamsContainer params){ oOwner->funcName(params); };

I hope this helps!

Syllogistic answered 7/11, 2011 at 2:12 Comment(2)
Most likely, those static functions will work as callbacks, and the void* parameter can't be changed. Still, the same approach could be used, just cast the void pointer to BaseClass* inside the function. However, this will incur a runtime cost, which is not necessary, since what the OP wants can easily be achieved statically.Staats
@Xeo: sure, but in my opinion this is a cleaner design with more maintainable code. Performance is not the only metric to use when considering what solution to implement.Syllogistic
I
0

Are searching for the function macro? It's a macro that expands to the current function name.

 __FUNCTION__
Impenitent answered 7/11, 2011 at 4:48 Comment(0)
R
0

I know it's an old question. Here a potential solution.

You can use this kind of habbit when you define a class:

class Foo: public Bar
{
  private:
    typedef Foo this_type; // your macro will work in every class defining this
  public:
    std::string description;
  public:
    static this_type* instanciate()
    {
      return new this_type;
    }
};
Remainder answered 9/3, 2023 at 8:55 Comment(0)
S
-2

No, a static method can only see static members of the class. It doesn't make sense for it to access instance members (as in, standard variables etc) as they don't exist unless the class has been instantiated.

It seems like you want something like the Singleton design pattern. This allows for only a single instance of the class to exist at a time.

Another way would be to have a static list of all instances of a class, then in the class constructor, add the this pointer to that list. As I say though, static members cannot access instance variables, as they may not exist at all.

I suppose the greater question is this: why do you need to access an instance variable from a static member? If you require access to an instance member, you should be calling the function in the context of the current instance, otherwise you're breaking the OOP paradigm pretty hard.

Saprogenic answered 7/11, 2011 at 1:8 Comment(7)
Sorry I should have been clearer. I'm not trying to access any instance variables. All I want is the type MyClass without explicitly writing it.Professed
Oh, sorry, so you want to instantiate an instance of the class which the static member belongs to?Saprogenic
Basically yes - but I can't just write MyClass* foo = new MyClass;Professed
Sadly then, I don't think there's a way. You could take the class name as a parameter to the macro though.Saprogenic
Yeah, that's what I'm going to do I think. I basically did all this to avoid having a second parameter to a macro. Thanks for your help.Professed
Just had a look around, see if your compiler supports the __CLASS__ macro, and it does what you expect. I think it's GCC specific though.Saprogenic
@DeadMG - I assumed in the first instance he wanted to access an instance member from a static method, in which case, a singleton would work, but not be the best solution, hence me asking why this was required. It turns out I interpreted the question wrong though, so yes, a singleton is not the way to go around this.Saprogenic

© 2022 - 2024 — McMap. All rights reserved.