views:

5932

answers:

7

How to simulate C# typeof-command behavior in C++?

C# example:

public static PluginNodeList GetPlugins (Type type)
{
 ...
}

Call:

PluginManager.GetPlugins (typeof(IPlugin))

How to implement this using C++? Maybe QT or Boost libraries provide a solution?

What about the case if you want to implement .GetPlugins(...) in a way that it loads those kinds of objects from a file (.so or .dll)?

+1  A: 

If you want complete typeof-like behaviour, you would have to use RTTI (run-time type information). On many compilers you have to explicitly activate usage of RTTI, as it incurs run-time overhead.

Then you can use typeid or dynamic_cast to find an object's type.

If you don't want to use typeid, you'd have to use inheritance, pointers and/or overloads. Boost might help you, but it's not too hard.

Example 1:

class Iplugin { ... }

class Plugin1 : public Iplugin { ... }
class Plugin2 : public Iplugin { ... }

void getplugins(Iplugin* p) {
    // ... you don't know the type, but you know
    // what operations it supports via Iplugin
}

void getplugins(Plugin1& p) {
    // expliticly handle Plugin1 objects
}

As you can see there are several ways of avoiding usage of RTTI and typeid.

csl
It is important that the casting taking place is over a class with a vtable - RTTI depends on it to perform dynamic_cast.
fbrereto
I don't think that RTTI incurs a runtime overhead. Rather the generated code is slightly larger, because the per class extra information needs to be stored with the vtable.As mentioned, class must have a vtable. Such a class should almost always have a virtual destructor (which also ensures that it has a vtable).
TrayMan
indirectly it can cause runtime overhead due to the larger code size.
rlbond
+2  A: 

You could use a dynamic_cast to test types as shown below:

IPlugin* iPluginPtr = NULL;
iPluginPtr = dynamic_cast<IPlugin*>(somePluginPtr);

if (iPluginPtr) {
    // Cast succeeded
} else {
    // Cast failed
}
daveg
Remember to note that RTTI must be enabled for this to work.
csl
Well yes, in other words, the language has to be C++. Standard C++ includes RTTI. The fact that compilers allow you to switch it off shouldn't be relevant. Doing so is nonstandard behavior. If you start disabling parts of the language, *of course* your code relying on it won't work. You might as well point out that the code has to be fed to a C++ compiler, rather than Fortran or C.
jalf
@jalf: Ok, you've convinced me -- it should be irrelevant what compilers do. But they do, so it doesn't hurt to note what you might have to do in practive. I guess compilers do this so that you "don't pay for what you don't use".
csl
+3  A: 

This behaviour is called RTTI (Run time type information). This technique is best to be avoided, but can be beneficial in some situations.

There are two big ways to solve this. The first way is to write an interface with a pure virtual function that returns a class specific integer reference code. This code can then be used to represent a specific type. These integers could be stored in a specific enumeration.

In derived classes you can then override the method and return that class specific type. During runtime, you can then call Plugin->getType() for instance, and it'll return its specific type. You can then perform a static_cast on the pointer to get the correct pointer of the derived type back.

The second way is to either use typeid to get the classtype of the object; but this is compiler dependant. You can also try casting your pointer using dynamic_cast; dynamic_cast returns a null pointer when it's being cast into the wrong type; and a valid one when being cast in a correct type. The dynamic cast method has a bigger overhead tho than the getType method described above.

Chaoz
RTTI is required to do type-safe dynamic downcasting. It does not provide "typeof" (GCC extension) or "auto"/"decltype" (C++0x) functionality.
Adisak
+2  A: 

Designing around this problem would be the best choice. Good use of object orientation can usually help but you can always create your own system for querying the type of an object by using a base class which stores an identifier for each object, for instance.

Always try to avoid using dynamic_cast as it most often uses string comparison to find the type of an object and that makes it really slow.

Flawe
A: 

Boost does have a typeof. C++ 0x doesn't call it typeof, but has both 'auto' and 'decltype' that provide the same kinds of functionality.

That said, I'm pretty sure none of those provides what you're really looking for in this case -- at most, they provide only a small piece of what you need/want overall.

Jerry Coffin
+1  A: 

You can use typeof() in GCC. With other compilers, it's either not supported or you have to do crazy template mangling or use "bug-features" that are very compiler specific (like the way Boost does it).

Adisak
A: 

Not directly answering the "how to get typeof() in C++", but I infer from your question that you are looking at how to do plugins in C++. If that's the case, you may be interested in the (not-yet)Boost.Extension library, and maybe in its reflection part.

Éric Malenfant