Consider the following:
struct B { };
template<typename T>
struct D : B
{
T t;
}
void g(int i) { ... }
void g(string s) { ... }
void g(char c) { ... }
void f(B* b)
{
if (dynamic_cast<D<int>*>(b))
{
g(dynamic_cast<D<int>*>(b)->t);
}
else if (dynamic_cast<D<string>*>(b))
{
g(dynamic_cast<D<string>*>(b)->t);
}
else if (dynamic_cast<D<char>*>(b))
{
g(dynamic_cast<D<char>*>(c)->t)
}
else
throw error;
};
Here there are only three possible types of T - int, string, char - but if the list of possible types were longer, say n, the if else chain would take O(n) to execute.
One way to deal with this would be to store an extra type code in D somehow and then switch
on the type code.
The RTTI system must already have such a code. Is there someway to get access to it and switch on it?
Or is there a better way to do what I'm trying to do?
static_cast − This is used for the normal/ordinary type conversion. This is also the cast responsible for implicit type coersion and can also be called explicitly. You should use it in cases like converting float to int, char to int, etc. dynamic_cast −This cast is used for handling polymorphism.
The dynamic type cast converts a pointer (or reference) to one class T1 into a pointer (reference) to another class T2 . T1 and T2 must be part of the same hierarchy, the classes must be accessible (via public derivation), and the conversion must not be ambiguous.
The primary purpose for the dynamic_cast operator is to perform type-safe downcasts. A downcast is the conversion of a pointer or reference to a class A to a pointer or reference to a class B , where class A is a base class of B .
dynamic_cast will no longer throw an exception when type-id is an interior pointer to a value type, with the cast failing at runtime. The cast will now return the 0 pointer value instead of throwing.
C++11 is almost there.
In C++03 it was impossible because the only way to get a compile-time constant (which case
requires) was through the type system. Since typeid
always returns the same type, it couldn't produce different alternatives for switch
.
C++11 adds constexpr
and type_info::hash_code
as a unique identifier of types, but doesn't combine them. You can use typeid
in a constant expression on a of type name or statically-typed expressions, but because hash_code
is a non- constexpr
function you cannot call it.
Of course there are various workarounds, one of which you describe, and the most general of which apply a visitor over a type vector using template metaprogramming.
Since only a few types are valid, you could solve this with virtual functions and template specialization instead:
struct B
{
virtual void g() = 0;
}
template<typename T>
struct D : public B
{
T t;
};
template<>
struct D<int> : public B
{
int t;
void g() { /* do something here */ }
};
template<>
struct D<std::string> : public B
{
std::string t;
void g() { /* do something here */ }
};
template<>
struct D<char> : public B
{
char t;
void g() { /* do something here */ }
};
void f(B* b)
{
b->g();
}
This will fail at compile-time if you provide the wrong types, instead or requiring runtime checks (which C++ is quite bad at).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With