Answer the question
In order to leave comments, you need to log in
RTTI vs template magic?
There is a class structure:
class IObject {
public:
virtual bool Method() = 0;
template<class T> T * As() { return (T*)this; } // да-да, не dynamic_cast.
}
class Object1 : public IObject {
public: virtual bool Method() { /* some logic */ }
}
class Object2 : public IObject {
public: virtual bool Method() { /* some logic */ }
}
class NamedObject : public IObject {
public:
NamedObject(const std::string& nm, IObject * o) : name(nm), obj(o) {}
virtual bool Method() { return obj->Method(); }
std::string& Name() { return name; }
IObject * Object() { return obj; }
private:
IObject * obj;
std::string name;
}
template<typename T>
inline bool isA(IObject * obj)
{
return dynamic_cast<T*>(obj) != null ||
(isA<NamedObject>(obj) && isA<T>(obj->As<NamedObject>()->Object()));
}
template<>
inline bool isA<NamedObject>(IObject * obj)
{
return dynamic_cast< NamedObject* >(obj) != null;
}
Answer the question
In order to leave comments, you need to log in
From the description it is not clear what the ultimate goal is, what exactly do you want to do?
if you understand correctly what you are trying to do, then ciaranm.wordpress.com/2010/05/24/runtime-type-checking-in-c-without-rtti/ is the same, but written more accurately and in 2 versions, you need the last one ( at the end of the article), roughly speaking, a unique integer is generated for each type, and the type is checked using it.
LLVM and Clang use something similar. Here is the header implementing isa and dyn_cast llvm.org/docs/doxygen/html/Casting_8h_source.html
To support this in your classes you need to implement two classof() methods like clang.llvm.org/doxygen/Comment_8h_source.html
To support using objects -wrapper implement those template specialization simlify_type.
You want to work with objects through a pointer to the IObject base class, and you want to implement isA using templates. This is not possible, since template instantiation occurs at compile-time, while IObject pointers are initialized at run-time. IObject is passed by pointer as an argument to the NamedObject constructor, so the obj type is known only at run-time and RTTI is indispensable here.
We take the idea mentioned by the link in the posts above and make an example for it:
#include <iostream>
class TypeIdGenerator
{
public:
template <typename T>
static const int GetId()
{
static const int Id = GetNextId();
return Id;
}
private:
static int GetNextId()
{
static int Id = 0;
return Id++;
}
};
struct ICast
{
virtual ~ICast()
{
}
virtual void const* Cast(int id) const = 0;
virtual void * Cast(int id) = 0;
};
template <typename T>
class CastImpl
: public T
{
public:
virtual void const* Cast(int id) const
{
return id == TypeIdGenerator::GetId<T>() ? this : 0;
}
virtual void * Cast(int id)
{
return id == TypeIdGenerator::GetId<T>() ? this : 0;
}
};
template <typename T>
T* MyCast(ICast *obj)
{
return reinterpret_cast<T *>(obj->Cast(TypeIdGenerator::GetId<T>()));
}
template <typename T>
T const* MyCast(ICast const *obj)
{
return reinterpret_cast<T const *>(obj->Cast(TypeIdGenerator::GetId<T>()));
}
class A
: public ICast
{
public:
void mtd() const
{
std::cout << __FUNCTION__ << std::endl;
}
};
int main()
{
ICast const &obj = CastImpl<A>();
A const *a = MyCast<A>(&obj);
if (a)
a->mtd();
return 0;
}
If you want to load dynamically, then template magic is not the way to go. This will require the union of namespaces, which will eventually require dynamically linked libraries to give unique names among all modules.
I did not refuse inheritance at home, because template magic, even if after a bunch of perversions and gives something, then there is a loss of development time, high code complexity.
I don't know what exactly you want. So in general I will try to tell my approach. Implemented an elementary mechanism. There is a basic interface, empty. All others inherit from it. The dynamic library implements 4 mandatory methods CreateInstance, DestroyInstance - for creating and deleting objects and CreateEnumerator, DestroyEnumerator - for creating an enumeration of available objects within the library. I made a simple library manager, a factory and an object of the shared_ptr type, only with a link to the library. The result is a simple code
Instance<IInterface> obj = mgr->CreateInstance<IInterface>("identificator");
CreateInstance uses dynamic_cast to cast to the desired one, in case of an error it throws an exception.
In general, he is still interested in why his own implementation of a simple RTTI, which already exists.
Here's another option for you:
pastebin.com/RZAY789w
can:
typedef std :: unique_ptr < IObject > ptr ;INamedObject also implements IObject
ptr p = CreateObject < Object3 > ( ) ;
assert ( FastObjectCast < Object3 > ( p. get ( ) ) ) ;
assert ( FastObjectCast < Object1 > ( p. get ( ) ) ) ; // Object3 inherits Object1
assert ( !FastObjectCast < INamedObject > ( p. get ( ) ) ) ; // p is unnamed Object3
ptr q = CreateObject < Object3 > ( "some name" ) ;
assert ( FastObjectCast < Object3 > ( q. get ( ) ) ) ;
assert ( FastObjectCast < Object1 > ( q. get ( ) ) ); // Object3 inherits Object1
assert ( FastObjectCast < INamedObject > ( q. get ( ) ) ) ) ; // p is named Object3
template < class T > T * As ( ) { return ( T * ) this ; }You need to use static_cast, because after the cast, the pointer can change the value by a couple of bytes (this is due to multiple inheritance, if it exists in the hierarchy).
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question