As the title suggests, I am looking for a fast way of runtime typechecking. To illustrate my problem, imagine you have a class hierarchy like the following:
Base
/ \
A D
/ \ / \
C B F E
\ /
G
My program holds all instances of any class in a single list as Base_ptr because all these classes share common tasks. Now at some point some derived classes will need to know about the existence of an instance of another class. So far so good, I know about dynamic_cast and the typeid()-operator, but both have some mayor drawbacks:
dynamic_cast consumes a lot of processing time if the types are incompatible (e.g. try to cast instances of E to C)
typeid() does not work in "isTypeOrSubtype"-cases, e.g. you need all instances of D or derived from D (so Es, Fs and Gs as well)
The ideal solution would be some kind of "isTypeOrSubtype"-test and only casting, if this test returns successfully. I got an own approach with some macro definitions and precalculated classname hashes, but it is very ugly and hardly maintainable. So I am looking for a cleaner and faster way of dynamic type and subtype checking that can check far more than 20million times per second.
I wrote an answer to my own question as this is a different approach to avoid RTTI but no real answer to a fast way of dynamic type/subtype check.
This still isn't a clean solution, but the best I could think of until now.
If every class in this hierarchy has the following characteristics, I can skip most of the RTTI.
every class should have a private member: static SecureVector<[class]*> s_Instances; where SecureVector<T> is a thread-safe vector.
at the end of every constructor, s_Instances.push_back(this); should be called, to keep track of a newly created instance of that class
at the beginning of the destructor, s_Instances.erase(this); should be called, to remove this instances reference
every class should have a public function: static const SecureVector<[class]*>& Instances() { return s_Instances; } to get an unmodifiable vector containing all instances of this or any derived class
What this does is, every time a constructor is called, the instance adds itself to its own list of instances. When derived classes call their super constructor, the super class adds itself to its respective list of instances.
E.g. if I randomly create 100 instances in the above hierarchy, there would allways be 100 entries in my Base class Instances() vector.
In code this would look like this:
class Base
{
static SecureVector<Base*> s_Instances; // 1. condition
public:
Base()
{
s_Instances.push_back(this); // 2. condition
}
~Base()
{
s_Instances.erase(this); // 3. condition
}
static const SecureVector<Base*>& Instances() { return s_Instances; } // 4. condition
};
This is still just as a workaround as the four conditions have to be added manually (or by macro or something like it).
Some time ago I used something like this:
// the actual type is irrelevant, const char*, int, ...
// but const char* is great for debugging, when it contains the actual class name
typedef const char* TypeId;
class Base {
// actually the type id is not the value, but its memory location !
// the value is irrelevant (but its a good idea to set it to the class name)
static TypeId s_myTypeId;
public:
static TypeId* getClassType() { return &s_myTypeId; }
virtual TypeId* getInstanceType() { return &s_myTypeId; }
static TypeId* getClassBaseType() { return NULL; }
virtual TypeId* getInstanceBaseType() { return NULL; }
virtual bool isType( TypeId* type ) { return type==getInstanceType(); }
virtual bool isTypeOrSubType( TypeId* type ) { return isType(type); }
};
template< class MyBase >
class TBase : public MyBase {
// actually the type id is not the value, but its memory location !
// the value is irrelevant (but its a good idea to set it to the class name)
static TypeId s_myTypeId;
public:
static TypeId* getClassType() { return &s_myTypeId; }
virtual TypeId* getInstanceType() { return &s_myTypeId; }
static TypeId* getClassBaseType() { return MyBase::getClassType(); }
virtual TypeId* getInstanceBaseType() { return MyBase::getInstanceType(); }
virtual bool isType( TypeId* type ) { return type==getInstanceType(); }
virtual bool isTypeOrSubType( TypeId* type ) { return isType(type) || MyBase::isTypeOrSubType(type); }
};
// by deriving from TBase<Base>, a new instantiation of s_myTypeId was created,
// so the class now has its very own unique type id,
// and it inherited all the type resolution magic
class A : public TBase<Base> {
};
// NOTE: class B must not derive directly from A, but from TBase<A>
// imagine a hidden class between B and A,
// actually B inherits from the TBase<A> instantiation, which in turn inherits from A
class B : public TBase<A> {
};
// you will also need to instantiate the static members
// hereby the memory location will be reserved,
// and on execution that memory location becomes the unique type id
#define IMPLEMENT_RTTI(CL) TypeId CL::s_myTypeId = STRFY(CL)
// one per class per source file:
IMPLEMENT_RTTI(Base);
IMPLEMENT_RTTI(A);
IMPLEMENT_RTTI(B);
// example usage:
A a;
B b;
b.getInstanceType()==B::getClassType(); // TRUE
b.getInstanceBaseType()==A::getClassType(); // TRUE
B::getClassBaseType()==A::getClassType(); // TRUE
b.isType( B::getClassType() ); // TRUE
b.isType( A::getClassType() ); // FALSE
b.isTypeOrSubType( B::getClassType() ); // TRUE
b.isTypeOrSubType( A::getClassType() ); // TRUE
b.isTypeOrSubType( Base::getClassType() ); // TRUE
It is safe, fast and easy to use. You just have to obey two rules:
do not inherit directly from a class X, but inherit from TBase<X>,
and add an IMPLEMENT_RTTI(Me) to source file.
There is one drawback: it does not yet support multiple inheritance. But it would be possible with a few changes.
And probably the TypeId type should be composed like typedef const char* TypeLoc and typedef TypeLoc* TypeId. Maybe just a question of taste.
If your program knows about all the sub types that will be tested against, you can use a virtual interface that returns a pointer to the sub type. As noted by downvotes and comments, this is not the most flexible approach, since it requires the base class have knowledge of all the derived classes. However, it is very fast. So there is a trade off of flexibility to performance.
class Base {
//...
virtual A * is_A () { return 0; }
virtual B * is_B () { return 0; }
//...
template <typename MAYBE_DERIVED>
MAYBE_DERIVED * isTypeOrSubtype () {
//...dispatch to template specialization to call is_X()
}
};
//...
class A : virtual public Base {
//...
A * is_A () { return this; }
};
On IDEONE, the suggested technique is 20 to 50 times faster than using dynamic cast.1 The implementation uses macros to allow a new class to be added to a single place, and the proper expansions to the base class occur in an automated way after that.
(1) - I originally clocked it closer to 100 times as fast, but this was without the isTypeOrSubtype() wrapper method that I added to simulate the desired interface.
If flexibility has a higher value than performance, then a slightly less performant solution is to use a map to associate types and corresponding pointer values (having the pointer values removes the need for a dynamic cast). The map instance is maintained in the base class, and the associations are made by the constructors of the subclasses. Whether a regular map or a unordered_map is used will depend on how many subclasses virtually inherit the base class. I would presume the numbers will be small, so a regular map should suffice.
class Base {
std::map<const char *, void *> children_;
//...
template <typename MAYBE_DERIVED>
MAYBE_DERIVED * isTypeOrSubtype () {
auto x = children_.find(typeid(MAYBE_DERIVED).name());
return ((x != children_.end())
? static_cast<MAYBE_DERIVED *>(x->second)
: 0);
}
};
//...
class A : virtual public Base {
//...
A () { children_[typeid(A).name()] = this; }
//...
};
On IDEONE, this second suggestion is 10 to 30 times faster the using dynamic cast. I don't think IDEONE compiles with optimizations, so I would expect the times to be closer to the first suggestion on a production build. The mechanism as implemented uses typeid(...).name() as the key to the map.2
(2) - This assumes that typeid(...).name() returns something similar to a string literal, and always returns the same string pointer when operating on the same type. If your system does not behave that way, you can modify the map to take a std::string as the key instead, but performance will be degraded.
dynamic_cast would work wonderfully for this!
Base *instance = //get the pointer from your collection;
A* ap = dynamic_cast<A*>(instance);
D* dp = dynamic_cast<D*>(instance);
if(ap) {
//instance is an A or a subclass of A
}
if(dp) {
//instance is a D or a subclass of D
}
This will work for more specific checks as well. So you could check for any type you want.
Related
I'm trying to write a Unity-style get component method. This is my code so far. It compiles but will return the first component it finds rather than the correct one. I think I'm using static_cast wrong. What is a better way to do this? Note I don't want to hard code component types, I want to be able to compile this engine and use anything that inherits from Component to be able to use this system. Also note that each component needs to return as itself, not a component *, as this would hide child functionality.
compStruct.components is a vector of component *s.
template <typename CompType>
inline CompType getComponent()
{
for(Component * currComp : compStruct.components)
{
if (static_cast<CompType>(currComp)!= nullptr)
{
return static_cast<CompType>(currComp);
}
}
return nullptr;
}
Here is an example of a generic component
#pragma once
#include "Component.h"
#include "Animation2D.h"
class AnimationComponent : public Component
{
public:
AnimationComponent(GameObject*x) :Component(x) {}
~AnimationComponent() {}
void stepAnimation(double delta);
//add overload for 3d animations
int addAnimation(Animation2D);
void setAnimation(int);
private:
};
And the component base class:
#pragma once
class GameObject;
class Component
{
public:
Component(GameObject * h) { host = h; }
virtual ~Component() {}
GameObject* getHost() { return host; }
protected:
GameObject * host = nullptr;
};
There's some fundamental misunderstanding about static_cast: it will just do the cast, and it is your responsibility to assure the pointer casted actually points to an object of the target type. static_cast will only return a null pointer if the source pointer already was itself, but never on type mismatch!
class B { /*...*/ };
class D1 : public B { };
class D2 : public B { };
D1 d1;
B* b = &d1;
D2* d2 = static_cast<D2*>(b);
d2 will be a pointer to d1 (in some cases involving multiple inheritance there can be an offset), but interpret the latter's data totally differently (unless D1 and D2 are layout compatible) and you might end up in hell!
Now first off, I personally prefer a modified signature:
template <typename CompType>
inline CompType* getComponent();
// ^
It allows calling your function like getComponent<SomeType>() instead of getComponent<SomeType*>(), additionally it allows using pointers inside the function body, which is way clearer, see my my appropriately adjusted code below.
Then what you actually need is a dynamic_cast (adjusting your code a little to my personal preferences...):
CompType* result = nullptr; // pointer: see above!
for(Component * currComp : compStruct.components)
{
result = dynamic_cast<CompType*>(currComp);
if(result)
break;
}
return result;
Edit: Catching up Nshant Singh's comment:
dynamic_cast actually is quite expensive.
An alternative could be an unordered_map, replacing your vector (example how to set up can be found at type_index documentation; of course, you'd place your objects instead of strings...). Then your lookup might look like:
auto i = map.find(std::type_index(typeid(CompType));
return i == map.end() ? nullptr : static_cast<CompType*>(i->second);
// now, you CAN use static cast, as the map lookup provided you the
// necessary guarantee that the type of the pointee is correct!
static_cast is definitely not what you want: it's static (compile time), so it cannot determine any runtime information.
What you want is dynamic_cast instead. Note that this has several requirements, all of which are fulfilled by your code:
The classes must be polymorphic. That's covered, because Component has a virtual destructor.
The classes must be defined (not just declared) at the point of the cast. That's covered as well, because getComponent is a template and the type in the cast depends on its template parameters (it is one, in fact). Therefore, the definition only needs to be visible where the template is instantiated (i.e. where getComponent is called). Since you're presumably doing the casting to access the concrete component's members, you must have its definition visible, so all is well.
I have some classes:
class Base
{
public:
virtual void Something() = 0;
}
class A : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForA();
}
class B : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForB();
}
and an array:
Base* MyMembers[2];
MyMembers[0] = new A;
MyMembers[1] = new B;
and I want to do:
A* pointer_to_a = Get(0);
B* pointer_to_b = Get(1);
Is there any good way to implement this Get() function?
My solution is:
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
But first thing is that I have to write
A* pointer_to_a = Get<A>(0)
Which requires an additional <A>;
Second thing is that if somehow the new is screwed up like:
MyMembers[0] = new B;
Then the Get() is failed.
What I want is something like an automatic mechanism which can maps index 0 to A.
Extra details:
Actually I have 80 different classes derived from Base (They are my User Interfaces),
and my need is to get the real classes (the real UIs) to do things.
The functions I need to use are the above SpecialActionForA()...etc.
The Something() is also used, but is in the initialization stage of these UIs, or something managed by the UI manager system.
You cannot do unknown* Get(int) in principle as it will require two or more functions having the same name but differing only by return value. C++ explicitly prohibits this.
The closest function that you can get is this:
template <typename T> T* Get() {
static T* instance = new T;
return instance;
}
so you will be able to use it as:
A *a = Get<A>();
B *b = Get<B>();
Overloading of function works by looking up the argument list. It is not possible to understand what kind of the value you want by judging only the return type. Thus compiler forces you to give extra detail to instantiate the template. So your options are:
Base *Get(int N) {
return MyMembers[N];
}
or
A *GetA(int N) {
return MyMembers[N];
}
B *GetB(int N) {
return MyMembers[N];
}
or
template <typename T> void Get(int N, T *&item) {
item = (T*)MyMembers[N];
}
A* pointer_to_a;
B* pointer_to_b;
Get(0, pointer_to_a);
Get(1, pointer_to_b);
or your own
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
Without knowing your usage scenario, it'll be a bit hard to provide a useful answer, but I actually do believe what you want is type matching. So what you do is that you pass your variables around as Base pointers until I you actually need to know the concrete underlying type, at this point you do a matching on the underlying type of your base pointer. This is works pretty much alike a switch statement mixed with lambdas, I'll try to provide an example.
...
Base* ptr = some_argument;
// Here we need the underlying type, so we'll do a match
Match(ptr)
{
Case(A* a)
{
// this is invoked if ptr happened to hold an A, now do something A specific.
}
Case(B* b)
{
// this is invoked if ptr happened to hold a B, now do something B specific
}
Otherwise()
{
// this is invoked whenever none of the above are
}
}
EndMatch;
...
This is an alternative to the usual solution, which is virtual pointers in the base class, and overriding. Note that type matching is commonly used in functional languages. For C++ there's a cleaver solution to achieving this, by Yuriy Solodkyy one of Bjarne Stroustrup's PhD students.
The short introductury paper can be found here;
https://parasol.tamu.edu/~yuriys/papers/OPM13EA.pdf
For a more information, check out hvis paper, which was presented to the ISO comitee; Open and Efficient Type Switch for C++ by Stroustup, Dos Reis and Solodkyy
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf
For the source code behind these papers goto Yuriys homepage at;
https://parasol.tamu.edu/~yuriys/pm/
If the number of classes you've got is truly closed, then consider using closed algebraic data types, as with boost::variant.These are have a few advantages over the unrestricted open algebraic data types, in that the compiler can usually ensure exhaustive matching, and in that the closed nature allows for more optimized pattern matching implementations, though at the cost of flexibility.
Also do note that boost::variant works nicely on C++03!
Do however please consider if you really need pattern matching or polymorphic dispatching. Both approaches are advantages and downsides, the main advance of the pattern matching approach, is that you aren't required to change your classes, and that you avoid polluting your base class with ultra specific virtual methods, which may only be called in a single location.
I'm trying to solve the following problem. I have a vector (it's a custom structure actually, but a vector is a good enough substitute for this issue) of pointers to a custom class A. Class A can actually store either a type_a pointer or a type_b pointer (these types are quite different and are not related to each other). Right now that's implemented by keeping both, setting them to NULL and then having a bunch of if/else statements later on to check which type it is and perform appropriate action.
class A {
public:
A() : p1(NULL), p2(NULL) {}
type_a * p1;
type_b * p2;
};
std::vector<A *> v;
...
if (v[0]->p1 != NULL) { /* do this */ }
else if (v[0]->p2 != NULL) { /* do that */ }
I plan to add more pointers to class A, and so the above is starting to become a hassle. The solution that I'm currently trying to make work is using boost::variant instead, to have:
class A {
public:
boost::variant<type_a*, type_b*> p;
};
The problem I have encountered though, is that one of my actions involves calling a function that would assign some values to a variable depending on what type of p I have. This is what it is now and the appropriate process_stuff function is called inside one of the above if/else statements:
class B { /*...*/ };
void process_stuff(type_a * p, B * b) {
b->m_var = p->fn1();
}
void process_stuff(type_b * p, B * b) {
b->m_var = p->fn2();
}
I can't get this to work with boost::static_visitor since (as far as I understand) I can't have a non-variant type as an argument in binary visitation, nor can I have a non-const operator() to make the second variable a member of the visitor class and modify that inside operator() with unary visitation. So I'm confused how to convert the above process_stuff function to play along with boost::variant.
Btw I'm not attached to boost::variant and would take other solutions.
You just need a stateful visitor. I'm typing this from a vague memory of exactly what visitors look like, but you should be able to fix any mistakes I make.
class process_stuff_visitor : public boost::static_visitor<void> {
B* m_b;
public:
process_stuff_visitor(B* b) : m_b(b) {}
void visit(type_a* a) const { m_b->m_var = a->fn1(); }
void visit(type_b* b) const { m_b->m_var = b->fn2(); }
};
// actual processing:
boost::apply_visitor(v[0], process_stuff_visitor(the_b));
Alternatively since you assign to the same member of B, you could just extract the value-generating part.
struct generate_stuff_visitor : public boost::static_visitor<TypeOfMVar> {
TypeOfMVar visit(type_a* a) const { return a->fn1(); }
TypeOfMVar visit(type_b* b) const { return b->fn2(); }
};
the_b->m_var = boost::apply_visitor(v[0], generate_stuff_visitor());
A very general object-oriented way of doing what you want to do (if I understand you correctly) is to create a virtual base class for types a and b (and any further types you want) which defines a pure virtual method. This method will return something different for each type (for example, type_b::method could return 'b', while type_a::method could return 'a'), so when you call the method on your unspecified type, you will be told what type it is.
From there, you can use the return value of the identifying method to be the subject of a switch statement, or some other conventional control structure to invoke the correct behavior.
I would like to define a completely generic mapping in c++ where I can map anything to anything.
I tried std::map but what should K and V be to make it general enough so I can map primitives or objects (as keys) to other primitives or objects (as values).
Or is there another mechanism I could use?
EDIT: For clarification, I am trying to define a relationship in the base class (from which all my classes are derived) that will allow me to attach arbitrary data to my classes. The simplest approach would be a be a name-value pair, where the above key is a string. I was wondering if i do something more generic?
Impossible- as it should be. Such a mapping would be worthless, since you can't depend on any meaningful behaviour of either key or value, and it's impossible to design either a binary relation or hash function that would be meaningful across "anything", or that could operate on any type, so it's nowhere near even the realm of possible.
Edit: There is nothing preventing std::unordered_map<std::string, boost::any>- or indeed, boost::any which happens to hold a std::unordered_map of some types.
However, your design appears highly questionable. You're basically completely subverting the compiler for no apparent benefit. Why would you derive every class from a common base? And why on earth would you want to attach arbitrary data? The usual way to put data in a class is to put it in the class, not blow all your safety and performance and sanity by trying to coerce C++ into being an interpreted language.
It is possible - so in this point I disagree with #DeadMG.
It is worthless - in this point full agreement,
However I do not understand that concept of answering, I mean "don't do it" answers instead "it can be done in this way, but my advise is don't do it". I do not pretend to be "life teacher" - I am just answering,
For values - use something like boost::any.
For keys - it is more complicated - because std::map defines order in keys. So generic keys must follow thess rules:
If real keys types are the same - use order from the real keys
If real keys are not the same - you must define order between types (like order of typeinfo::name())
Generic keys must be copy constructible
Let see my proposal for keys (using type erasure):
template <typename T>
struct GenKeyTypeOrder;
class GenKeyImplInt {
public:
// true if before other Key in other
virtual bool before(const GenKeyImplInt&) const = 0;
// type value
virtual int typeOrder() const = 0;
virtual GenKeyImplInt* clone() const = 0;
virtual ~GenKeyImplInt() {}
};
template <typename RealKey>
class GenKeyImpl : public GenKeyImplInt {
public:
GenKeyImpl(RealKey realKey) : realKey(realKey) {}
// true if before other Key in other
virtual bool before(const GenKeyImplInt& r) const
{
const GenKeyImpl* rp = dynamic_cast<const GenKeyImpl*>(&r);
if (rp) return realKey < rp->realKey;
return typeOrder() < r.typeOrder();
}
// type value
virtual int typeOrder() const { return GenKeyTypeOrder<RealKey>::VALUE; }
virtual GenKeyImpl* clone() const { return new GenKeyImpl(*this); }
private:
RealKey realKey;
};
class GenKey {
public:
// true if before other Key in other
friend bool operator < (const GenKey& l, const GenKey& r)
{
return l.impl->before(*r.impl);
}
template <typename T>
GenKey(T t) : impl(new GenKeyImpl<T>(t)) {}
GenKey(const GenKey& oth) : impl(oth.impl->clone()) {}
~GenKey() { delete impl; }
private:
GenKey& operator = (const GenKey& oth); // not defined
GenKeyImplInt* impl;
};
// define for every type you want be used as generic key
template <>
struct GenKeyTypeOrder<int> { enum { VALUE = 0 }; };
template <>
struct GenKeyTypeOrder<std::string> { enum { VALUE = 1 }; };
Full example at ideone
See also this article
You will need to make K and V be special objects.
The object will need to include what object type it is.
struct {
void *pointer;
string type;
// int type; // this is also possible
} Object;
The above Object can point to anything. However, it also needs something to say what type it is, hence the type string.
Then you need to be able to cast the pointer back to the required type, by reading what is in type.
Eg.
if (type == "int") cout << (int*)(myobject.pointer) << endl;
Anyways, if you do something like this, you are almost starting to build a loosely-typed interpreter, because for any operation you want to do with the object, you will need to check its type (whether you are adding, concatenating or printing the value to stdout).
It is probably better if you use a class object, and use inheritance to store any data you need.
class Object {
public virtual string to_string() {
return "";
}
};
Then if you want to store an integer:
class Integer : public Object {
int i;
public string to_string() {
char str[50];
sprintf(str,"%d",i);
return string(str);
}
public Integer operator=(int a) {
i=a;
return this;
}
};
This way you can define an interface of all the functions you want all objects to support.
Note that making the base Object class have virtual functions means that if you say:
Integer a;
a=5;
Object object = (Object)a;
cout << object.to_string << endl; // prints "5"
So that the function called is that defined by the actual (true) type of the object.
i have a class with the following structure:
class myClass
{
private:
int type;
classOne objectOne;
classTwo objectTwo;
public:
myClass(classOne object)
{
this->objectOne = object;
this->type = 0;
}
myClass(classTwo object)
{
this->objectTwo = object;
this->type = 1;
}
}
i now want a method returning an object of type classOne if type is 0 and of type classTwo if type is 1. I do not want two methods to achieve this. the classes have different structures.
Is this even possible? Any suggestions are appreciated :)
You can use Boost.Variant to do this. A variant can be constructed directly from any value convertible to one of its bounded types. Similarly, a variant can be assigned any value convertible to one of its bounded types. Heres how you could use it in your class:
class myClass
{
private:
boost::variant<classOne, classTwo> obj;
public:
myClass(classOne object) : obj(object)
{
}
myClass(classTwo object) : obj(object)
{
}
};
It also provides a very convenient boost::get to retrieve the value from the variant.
You can use that to supply code for each bounded type you have(ie classOne and classTwo). Here is an example:
if (classOne * x = boost::get<classOne>(&obj))
{
//Code for classOne
}
else if (classTwo * x = boost::get<classTwo>(&obj)
{
//Code for classTwo
}
However, such code is quite brittle, and without careful attention will likely lead to the introduction of subtle logical errors detectable only at runtime. Thus, real-world use of variant typically demands an access mechanism more robust than get. For this reason, variant supports compile-time checked visitation via apply_visitor. Visitation requires that the programmer explicitly handle (or ignore) each bounded type. Failure to do so results in a compile-time error.
Visitation of a variant requires a visitor object. Like this:
class object_visitor
: public boost::static_visitor<>
{
public:
void operator()(classOne & x) const
{
//Code for classOne
}
void operator()(classTwo & x) const
{
//Code for classTwo
}
};
With the implementation of the above visitor, we can then apply it to obj, as seen in the following:
boost::apply_visitor( object_visitor(), obj );
Unless the two types are related (in which case you can create a function that will return a pointer/reference to the common ancestor) you cannot do that directly in C++.
C++ is a statically typed language, meaning that the type of every expression must be known at compile time, but you are trying to define a function whose return type depends on runtime values.
Depending on the particular problem to solve, there might be different approaches that you could take, including using type erasure (return a boost::any, boost::variant or your own type-erasure).
ClassOne and ClassTwo need to have the same return type then either via inheritance or composition. i.e ClassOne and ClassTwo need to be subclasses of the same super class OR they need to impl the same interface.
I am not sure why you would not use templates for your case.
You can have something like below:
template <class ClassType>
class myClass
{
private:
int type;
ClassType object;
public:
myClass(ClassType object_in)
{
this->object = object_in;
/*
C++ doesn't support reflection so I don't think there
is a robust way of doing the following at runtime.
*/
type = /* Get Type at runtime */;
}
/*
Have another method which return object in a straigtforward way.
*/
};
However, then this become trivial. Any more insight into what your use case is, such that you have to know the type?
Update:
If the ClassType is going to be an Object, you can have a const static int TypeID member for the class, which is set at compile time. You can then use it determine the Type at runtime.
If they're completely different structures, with no common base then an alternative way you can return them from the same function is to use void*.
However that's bad form in C++, usually indicating a design failure - either use two different functions, or use a common base class.
It's apples and oranges. If you put an apple into an recipe that calls for an orange it won't be the same recipe anymore.
The use of type-id is a sign that you need virtual functions for myClass. Even if the other two classes are totally independent, the fact that they are returned by the same function could easily make them inherit a base class. And also you can just return a pair containing class1, class2 and one of them can be null.
The first problem is how you will determine the class of which type has been returned. I think it is possible to return a pointer to structure of this type
struct res {
myClass* c1;
ClassOne* c2;
} ;
The field of the not chosen class is NULL, the other points to the object.