It is easier to explain on an example so,
class base {
//....
}
class derived1 : public base {
//...
}
In my library, there is a pointer o
I think the answer to this question is very difficult. Of course there is std::is_base_of and dynamic_cast. Both provide you with some very limited information. The third option is function overloading. With all of those techniques you can choose a special path in your code which should be executed.
std::is_base_of can be interpreted in a boolean context and it is derived from either std::true_type or std::false_type. This fact makes it possible to use it as paramter for a function and use compile time polymorphism via function overloading. This first example shows how to use it in a boolean context, but you don't have any further specific type information. So compilation will fail in most circumstances (see here for a further description):
template
void do_it1(T const& t) {
if (std::is_base_of::value) {
// we have a derived1
} else {
// we have a base
}
}
The second version is simple function overloading. Here compile time polymorphism is used but all runtime type information is lost (except virtual functions and dynamic_cast are used):
void do_it2(Base const& b) {
// we have a base your algorithm for base here
}
void do_it2(Derived2 const& d) {
// Derived algorithm here
}
Now the third version combines both:
template
void do_it3_impl(T const& t, std::true_type) {
// here t will be of a type derived from derived1
}
template
void do_it3_impl(T const& t,std::false_type) {
// here t will be of type not derived from derived1
}
template
void do_it_3(T const& t) {
do_it3_impl(t, std::is_base_of()); // here we forward to our impl
}
The third variant is normaly used for header only libraries which don't use runtime poylmorphism (search for std::advance for an excample).
Now to runtime polymorphism. Here you have the dynaminc_cast variant:
void do_it4(Base const* ptr)
if (derived1 const* obj = dynamic_cast(ptr)) {
// here we have obj with type derived1*
} else {
// here we have only base
}
If this variant is not fast enough you can implement your onw cast to derived1:
class derived1;
class base {
// as above
public:
virtual derived1 const* to_derived1() const {
return 0;
}
};
class derived1
: public base
{
// ...
virtual derived1 const* to_derived1() const {
return this;
}
};
void do_it5(Base const* ptr)
if (derived1 const* obj = ptr->to_derived1() {
// here we have obj with type derived1*
} else {
// here we have only base
}
This is fast but it scales very well for only very few (approximately 1) derived classes.
Last but not least you should think about your class design and deside what methods to make virtual and implement in base, derived1 or other classes. You should definitly look for strategy pattern.