Writing a get component method in c++ with templates - c++

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.

Related

Is there a way to simulate downcasting by reference

So, I have something along the lines of these structs:
struct Generic {}
struct Specific : Generic {}
At some point I have the the need to downcast, ie:
Specific s = (Specific) GetGenericData();
This is a problem because I get error messages stating that no user-defined cast was available.
I can change the code to be:
Specific s = (*(Specific *)&GetGenericData())
or using reinterpret_cast, it would be:
Specific s = *reinterpret_cast<Specific *>(&GetGenericData());
But, is there a way to make this cleaner? Perhaps using a macro or template?
I looked at this post C++ covariant templates, and I think it has some similarities, but not sure how to rewrite it for my case. I really don't want to define things as SmartPtr. I would rather keep things as the objects they are.
It looks like GetGenericData() from your usage returns a Generic by-value, in which case a cast to Specific will be unsafe due to object slicing.
To do what you want to do, you should make it return a pointer or reference:
Generic* GetGenericData();
Generic& GetGenericDataRef();
And then you can perform a cast:
// safe, returns nullptr if it's not actually a Specific*
auto safe = dynamic_cast<Specific*>(GetGenericData());
// for references, this will throw std::bad_cast
// if you try the wrong type
auto& safe_ref = dynamic_cast<Specific&>(GetGenericDataRef());
// unsafe, undefined behavior if it's the wrong type,
// but faster if it is
auto unsafe = static_cast<Specific*>(GetGenericData());
I assume here that your data is simple.
struct Generic {
int x=0;
int y=0;
};
struct Specific:Generic{
int z=0;
explicit Specific(Generic const&o):Generic(o){}
// boilerplate, some may not be needed, but good habit:
Specific()=default;
Specific(Specific const&)=default;
Specific(Specific &&)=default;
Specific& operator=(Specific const&)=default;
Specific& operator=(Specific &&)=default;
};
and bob is your uncle. It is somewhat important that int z hae a default initializer, so we don't have to repeat it in the from-parent ctor.
I made thr ctor explicit so it will be called only explicitly, instead of by accident.
This is a suitable solution for simple data.
So the first step is to realize you have a dynamic state problem. The nature of the state you store changes based off dynamic information.
struct GenericState { virtual ~GenericState() {} }; // data in here
struct Generic;
template<class D>
struct GenericBase {
D& self() { return *static_cast<D&>(*this); }
D const& self() const { return *static_cast<D&>(*this); }
// code to interact with GenericState here via self().pImpl
// if you have `virtual` behavior, have a non-virtual method forward to
// a `virtual` method in GenericState.
};
struct Generic:GenericBase<Generic> {
// ctors go here, creates a GenericState in the pImpl below, or whatever
~GenericState() {} // not virtual
private:
friend struct GenericBase<Generic>;
std::unique_ptr<GenericState> pImpl;
};
struct SpecificState : GenericState {
// specific stuff in here, including possible virtual method overrides
};
struct Specific : GenericBase<Specific> {
// different ctors, creates a SpecificState in a pImpl
// upcast operators:
operator Generic() && { /* move pImpl into return value */ }
operator Generic() const& { /* copy pImpl into return value */ }
private:
friend struct GenericBase<Specific>;
std::unique_ptr<SpecificState> pImpl;
};
If you want the ability to copy, implement a virtual GenericState* clone() const method in GenericState, and in SpecificState override it covariantly.
What I have done here is regularized the type (or semiregularized if we don't support move). The Specific and Generic types are unrelated, but their back end implementation details (GenericState and SpecificState) are related.
Interface duplication is avoided mostly via CRTP and GenericBase.
Downcasting now can either involve a dynamic check or not. You go through the pImpl and cast it over. If done in an rvalue context, it moves -- if in an lvalue context, it copies.
You could use shared pointers instead of unique pointers if you prefer. That would permit non-copy non-move based casting.
Ok, after some additional study, I am wondering if what is wrong with doing this:
struct Generic {}
struct Specific : Generic {
Specific( const Generic &obj ) : Generic(obj) {}
}
Correct me if I am wrong, but this works using the implicit copy constructors.
Assuming that is the case, I can avoid having to write one and does perform the casting automatically, and I can now write:
Specific s = GetGenericData();
Granted, for large objects, this is probably not a good idea, but for smaller ones, will this be a "correct" solution?

C++ fast dynamic type/subtype check

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.

variant variable interaction with a non-variant type

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.

variable return type in c++ class

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.

Dynamic cast and multiple inheritance

The dynamic_cast operator is returning zero (0) when I apply to a pointer that points to an instance of a multiply inherited object. I don't understand why.
The hierarchy:
class Field_Interface
{
public:
virtual const std::string get_field_name(void) const = 0; // Just to make the class abstract.
};
class Record_ID_Interface
{
public:
virtual bool has_valid_id(void) const = 0;
};
class Record_ID_As_Field
: public Field_Interface,
public Record_ID_Interface
{
// This class behaves as a Field and a Record_ID.
// ...
}
// A demonstration function
void Print_Field_Name(const Field_Interface * p_field)
{
if (p_field)
{
cout << p_field->get_field_name() << endl;
}
return;
}
// A main function for demonstration
int main(void)
{
Record_ID_As_Field * p_record_id = 0;
p_record_id = new Record_ID_As_Field;
if (p_record_id)
{
// (1) This is the trouble line
Print_Field_Name(dynamic_cast<Field_Interface *>(p_record_id));
}
return 0;
}
I want to have the Record_ID_As_Field to be treated as a Field_Interface, but also fit in where Record_ID_Interface are required.
Why is dynamic_cast in (1) above returning 0, and how do I resolve this?
I am using Visual Studion 2008 on Windows XP.
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses boost::shared_ptr.
Note: For simplicity, I am using fundamental pointers in this example. Actual code uses boost::shared_ptr.
And that's your problem right there: You cannot dynamic_cast a shared_ptr<A> to a shared_ptr<B> since those two types are not actually related to each other, even if A and B are.
Luckily in the specific case in your question the dynamic_cast shouldn't be necessary, since Record_ID_As_Field* should be implicitly convertible to a Field_Interface* (since the one is derived from the other). shared_ptr implements conversion operators that lift these implicit conversions to the respective shared_ptr objects, so shared_ptr<Record_ID_As_Field> should be implicitly convertible to shared_ptr<Field_Interface>.
If you leave out the dynamic_cast, it should work.
If you'd actually need to do a dynamic cast, you could use a special constructor provided by shared_ptr:
shared_ptr<Record_ID_As_Field> raf;
shared_ptr<Field_Interface> fi(raf, dynamic_cast<FieldInterface*>(raf.get());
(I'm not sure what would happen there if the dynamic_cast fails, so you should investigate what's the best way to handle that situation.)