cleversoap
cleversoap

Reputation: 95

C++ Get class type inside static function

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.

Upvotes: 9

Views: 5980

Answers (7)

Caduchon
Caduchon

Reputation: 5221

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

Upvotes: 0

jenkas
jenkas

Reputation: 971

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

Upvotes: 3

David Feurle
David Feurle

Reputation: 2787

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

 __FUNCTION__

Upvotes: 0

Miguel Grinberg
Miguel Grinberg

Reputation: 67509

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!

Upvotes: 0

iehrlich
iehrlich

Reputation: 3592

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++.

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477188

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.

Upvotes: 1

slugonamission
slugonamission

Reputation: 9642

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.

Upvotes: -2

Related Questions