Emir wrote: |
---|
You solution assumes that the derived classes can be sorted/ordered the same way numbers can. However, in my case, the "ordering" does not have to follow such rules. For example, A<B<C, but a new class D can be considered to be "less" than A, but "greater" than C. |
I may have misunderstood you, but I think the solution will work when the set of derived classes can be ordered in a sequence.
I think you criticize this code:
1 2 3 4
|
template<>
const int Derived<int>::m_type_index = 0;
template<>
const int Derived<char>::m_type_index = 1;
|
I never assumed that the above lines will not need special maintenance. Suppose, you want to create a new wrapper for class
Derived<short> and you want this new derived class to be between the classes
Derived<int> and
Derived<char> in the ordering. Then you will need to modify the code like this:
1 2 3 4 5 6
|
template<>
const int Derived<int>::m_type_index = 0;
template<>
const int Derived<char>::m_type_index = 1;
template<>
const int Derived<char>::m_type_index = 12;
|
lionishy wrote: |
---|
Why do you need any virtual table for a static member? :-)
They are static, they belong to class, not to the object. They can be resolved at compile time! |
I know what you are saying, but you indeed missed my point. Static variables indeed belong to the type. But the dynamic type of an object belongs to the object. That is the idea behind polymorphism and the vtable. Classically, the vtable is used in order to be able to resolve a call on some object based on its dynamic type. Something like dynamic overload resolution. But this dynamic type does not need to be used only for resolving calls in this way. It can be used for storing other type specific information. Like - what is the value of some constant, what is the address of some function, etc. For example, suppose the following language extension:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
struct A {
virtual static const int type_specific_value = 0;
};
struct B : A {
virtual static const int type_specific_value;
};
const int B::type_specific_value = 1;
struct C : A {
virtual static const int type_specific_value;
};
const int C::type_specific_value = 2;
int main()
{
B b;
C c;
A *p1 = &b;
A *p2 = &c;
cout << p1->type_specific_value << endl; //prints 1
cout << p2->type_specific_value << endl; //prints 2
}
|
The same can be used for static functions. As a matter of fact, currently the dynamic type is accessible only through an object instance, because it is only used for object-level methods. I argue that it should be possible to create the dynamic type as a separate meta-object allowing access to class level methods, resolved dynamically. Essentially, a person can always use function pointers for a single static function or object pointers for static member variable, but if you need a bunch of them, like an interface, it is inconvenient. I don't mean support for run-time introspection here. I only say, if we have the concept of dynamic type, why don't we allow all members of a type to benefit from run-time binding? And why do we keep the dynamic type as implicit instance data? Why don't we simply recognize it a separate entity that is automatically associated with an instance, but can be used by itself?
Regards