Detecting Inheritance during compile time - c++

I am unable to figure out why this code is returning false. I had the first version of partial specialization. It did not work, I tried with the second version. It did not work either.
UPDATE: I wanted to check if "Derived" is publicly derived from "Base".
UPDATE:
template<typename TDerived, typename TBase>
struct Derived_From
{
public:
static void constraints(TBase*, TDerived* ptr) { TBase* b = ptr; ignore(b); }
Derived_From() { void (*p)(TBase*, TDerived*) = constraints; ignore(p);}
};
I found the above code snippet in Strostrup's homepage. But, it does not let the code compile if the derived class is not publicly derived from Base.
template<class TBase, class TDerived>
struct IsDerived
{
public:
enum { isDerived = false };
};
template<class TBase>
struct IsDerived<TBase, TBase>
{
public:
enum { isDerived = true };
};
template<class TBase>
struct IsDerived<TBase&, TBase&>
{
public:
enum { isDerived = true };
};
int main()
{
cout << ((IsDerived<Base&, Derived&>::isDerived) ? "true" : "false")
<< endl;
cout << ((IsDerived<const Derived*, const Base*>::isDerived) ?
"true" : "false") << endl;
}

I always just use pointer initialization for this. Pointers implicitly convert only to a supertype (could be identity conversion or public base class), so it won't compile unless that relationship exists (and in the right direction).
e.g.
Parent* p = (Possibly_Derived*)0;
Oh wait, you're not wanting compilation to fail, but to set a variable? Here:
template<typename TParent>
bool is_derived_from( TParent* ) { return true; }
template<typename TParent>
bool is_derived_from( void* ) { return false; }
cout << is_derived_from<Parent>( (Possibly_Derived*)0 );
Here's a demo: http://ideone.com/0ShRF

Check out boost type traits, specifically the is_base_of template.

Firstly, I assume you want a generic method to work for any classes, without modifying or adding any function to the class. I think this template method cannot work. A derived class is not equal to the base class, and unless the two classes are EQUAL, the specialized struct will not be instantiated. Similarly, pointer to derived class is not equal to pointer to base class.
I assume you already know that people regularly use virtual functions to check if the "object" is of base class or derived class.
(Note that I am not saying what you want cannot be done - just that the results you are seeing are expected and the template approach will not work).

If I am right, you are calling the Template with 2 different Parameter types..
(IsDerived<Base&, Derived&>::isDerived)
Thus it will invoke
struct IsDerived
{
public:
enum { isDerived = false };
};
and this is why IsDerived<Base&, Derived&>::isDerived as well as IsDerived<const Derived*, const Base*>::isDerived is false.
calls like (IsDerived<Base&, Base&>::isDerived) will return True.
I wanted to check if "Derived" is
publicly derived from "Base".
I am not aware of Template based solution, and will keep a eye on this thread. but i usually exploit dynamic_cast to do this job, if ever needed.
If dynamic_cast cannot cast a pointer because it is not a complete object of the required class, it returns a null pointer to indicate the failure.
If dynamic_cast is used to convert to a reference type and the conversion is not possible, an exception of type bad_cast is thrown instead.

Related

Check for template class equality through base class pointer

Is it possible to check, through a base class pointer, whether different derived template classes are specialization of the same template class?
This is achievable through introducing an intermediate non-template base-class. However, i would like to know whether this pattern is avoidable when the sole purpose of this intermediate class is for identification:
class A{}
class B_base : public A{}
template<T>
class B : public B_base {}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B through a
// dynamic_cast to the intermediate class
if(dynamic_cast<B_base*>()){
// This is a B_base object,
}
}
}
Ideally, i would like something like this, to avoid the intermediate class.
class A{}
template<T>
class B : public A{}
// There may be other derived classes of A
template<T>
class C: public A{}
void main() {
// ... some vector of pointers to A derived objects
std::vector<A*> v;
for(auto& i : v){
// Check whether i is any specialization of B
if(templateTypeId(i) == templateTypeId(B*)){
// This is a B object with some unknown specialization
}
}
}
Different specializations of a template are entirely unrelated types for most purposes. Template argument deduction can deduce a template and its arguments from such a type, but that happens entirely at compile time. There is no guaranteed run time information that can tell whether a class is a specialization of a given template, whether two classes are specializations of the same template, etc.
So you would need to set up a way to test this yourself, but your intermediate class method is not the only option. The most straightforward way would be to put a way to test it into the base A class:
class A {
public:
virtual ~A() = default;
virtual bool is_B() const noexcept { return false; }
};
template <class T>
class B : public A {
public:
bool is_B() const noexcept override { return true; }
};
Though this gets a bit ugly if there are several different B-like categories to test for, and doesn't work if it should be possible to extend A with new subtypes, and then test for those subtypes in a similar way.
Another idea would be to associate the type check with an object address:
struct type_tag {
constexpr type_tag() = default;
type_tag(const type_tag&) = delete;
type_tag& operator=(const type_tag&) = delete;
};
class A {
public:
virtual ~A() = default;
virtual bool matches_type(const type_tag&) const
{ return false; }
};
inline constexpr type_tag B_tag{};
template <class T>
class B {
public:
bool matches_type(const type_tag& tag) const override
{ return &tag == &B_tag; }
};
This pattern also allows for categories of subtypes that don't come from just one template. It also doesn't prevent a new class from "lying" about its own type, if that might be a concern, but it might be best not to try to prevent that, but let any implemented derived class be responsible for its own behavior, which might mean it wants to act "almost exactly like" some other type.
May be a better design is to add required virtual functions to interface A, so that you can invoke them directly on A* without guessing the derived class. The latter is an anti-pattern because it defeats the purpose of polymorphism: the idea that a piece of code can work with object of different classes without knowing their exact type. You may as well put objects of different types into different containers and not use ploymorphism based on virtual functions at all.

I can't override Base class's method because my derived class is templatised

I try to override the base class function but because I have templatised its child/derived/sub class I can't override the function depending on which type I instantiate the template with.
struct BaseType
{
virtual double getPropertyValue() = 0;
};
template <typename T>
struct NumberType : BaseType
{
T propertyValue;
T getPropertyValue() override { return propertyValue; } // I would like this to return whatever T is.
};
int main()
{
std::vector<BaseType*> vectr;
NumberType<double> doubleType; // This is fine, overrides the base function
NumberType<int> intType; // Has no overrider, won't compile
}
So I thought maybe I could templatise also the Base class, so that the base class function returns T also. But if I do this I won't be able to keep them in a container or point to them, because they'll all be of different Base< type> types.
I also thought about templatising Base and having it inherit from an even higher parent (which isn't templatised), but I run into the same problem.
Is there any way around this?
You can do this if the return value T is covariant with the return value of the pure virtual function. But sadly a T will not, in general, be covariant with a double.
Accepting that you're mixing up static and dynamic polymorphism techniques, which might be a design flaw, you could define
struct Cov {};
with
struct BaseType
{
virtual Cov& getPropertyValue() = 0;
};
Then,
template <typename T>
struct NumberType : BaseType
{
T propertyValue;
T& getPropertyValue() override { return propertyValue; }
};
where T is a child class of Cov: this relationship means that T& is a return type that's covariant with Cov&, and so compilation will succeed. Doing it this way also obviates a value copy of T being taken. You might also find it convenient to build conversion operators for the various Ts that end up getting built that have primitive type return values.
You can also introduce const reference return types to suit the exact requirements.
BaseType has a contract that is binding for all its descendants. It says says that getPropertyValue returns double. NumberType doesn't get to modify the contract, it's set in stone.
Let's pretend the contract is not there.
BaseType& base = BaseContainer.getSome();
// base can be NumberType<complex> or
// or NumberType<tensor<double,4,4,4>> or NumberType<padic<5>>
// or a type that is not even thought of yet
// as of now.
what = base.getPropertyValue(); // how should 'what' be declared?
There's no way to use the result of base.getPropertyValue() if we don't know what it is.
Making the return type covariant doesn't really help. It just shifts the problem from BaseType to whatever base class BaseType::getPropertyValue() returns.
You need to come up with a usable interface of BaseType and stick to it in all descendant classes.

Casting specialized base pointer to derived pointer that specializes on additional template parameter ("adding on" a specialization)

I'd like to cast a base class pointer to a derived one in order to take advantage of some methods unique to the derived class. Here's an Ideone of a simple example that works:
template<typename A>
class Base {};
template<typename A, typename B>
class Derived : public Base<A> {
public:
void doSomething() {}
};
int main() {
Base<int>* foo = new Derived<int, double>;
static_cast<Derived<int, double>*>(foo)->doSomething();
return 0;
}
Now, the problem is that my foo is actually a member of a templated class,
template<typename A>
class Container
{
public:
Base<A>* foo;
};
and at the time I cast, I don't know what A is:
int main() {
Container<int> container;
container.foo = new Derived<int, double>;
// a lot of code later...
static_cast<Derived< /* ??? */ , double>*>(container.foo)->doSomething();
return 0;
}
Then I thought this might be possible if I could somehow store what A is in my base class, like
template<typename A>
class Base
{
public:
static type template_type = A; // made-up syntax
};
so that I can refer to it like
static_cast<Derived<container.template_type, double>*>(container.foo)->doSomething();
but according to this question it's not possible to store types in C++.
How do I achieve this cast without knowing A?
That is, how do I cast a specialized base pointer to a derived pointer that specializes on an additional template parameter? In less technical terms, I just want to take a Base pointer and tack on the other specialization necessary to form the Derived pointer.
Usually it is not wise to do an up-cast and there is usually a better design that you may use to avoid the need of up-cast at all, but if you really need it, then you may use dynamic_cast to do this.
this operator try to convert from one type to another type dynamically and if conversion is not possible, it will return nullptr. But remember that it only work for polymorphic types(types that have at least one virtual function) so in this case your Base class must be polymorphic(since you are holding a pointer to base class, you possibly need a virtual destructor to allow delete to work on base pointer and this make Base a polymorphic class).
But to remember a type in C++, you have 2 options:
Use typedef:
You may use typedef to hold type information in the class:
template< class A >
class my_class
{
public:
typedef A input_type;
};
template< class T >
void do_something(T const& t)
{
typename T::input_type n;
do_something_on_input_type(n); // possibly overloaded for different input types
}
this approach is really fast and have no overhead in runtime, but you can use it only in cases when you want to do something in compile time. and if the type of pointer is not determined until runtime this approach is not useful.
Use std::type_info
Using this you can actually hold type information with the class:
class Base { virtual std::type_info const& get_type() const = 0; };
class Child : public Base
{
virtual std::type_info const& get_type() const { return typeid(Child);
void child_specific_function() { /**/ }
}
class ChildOfChild : public Child
{
virtual std::type_info const& get_type() const { return typeid(ChildOfChild); }
// ...
};
void do_something(Base* base)
{
if (base->get_type() == typeid(Child))
{
static_cast<Child*>(base)->child_specific_function();
}
}
This sound really interesting but, it is only useful when you know exact type of the object and it does not work for derived types, so this approach work for Child but not for ChildOfChild

Check if class is derived from a specific class (compile, runtime both answers available)

It is easier to explain on an example so,
class base {
//....
}
class derived1 : public base {
//...
}
In my library, there is a pointer of base class. The user of the library have to make classes derived from either base or derived1 and assign pointer to that class.
How can I check what class is user-defined class derived from?
I have some remarks on the proposed compile-time x runtime solutions. In addition to when they are evaluated, is_base_of and dynamic_cast have different requirements and their answers can be different.
(1) First of all (as pointed out by others) to use dynamic_cast, base and derived classes must be polymorphic (must have at least one virtual method). is_base_of doesn't require the types to be polymorphic.
(2) The operands of is_base_of are both types whereas dynamic_cast needs a type (inside < >) and an object (inside ( )).
(3) dynamic_cast and is_base_of can give different answers (or one can compile while the other doesn't) depending on the type of inheritance (public vs protected or private). For instance consider:
struct B { virtual ~B() {} }; // polymorphic, so it can be used in a dynamic_cast
struct D1 : public B {}; // polymorphic by (public) inheritance
struct D2 : private B {}; // polymorphic by (private) inheritance
D1 d1;
D2 d2;
We have
static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");
assert(dynamic_cast<B*>(&d1));
assert(!dynamic_cast<B*>(&d2)); // Notice the negation.
Actually the last line yields a compiler error in GCC (error: 'B' is an inaccessible base of 'D2'). VS2010 does compile it (yielding just a warning similar to GCC's error message).
(4) The requirements on the classes being polymorphic can be relaxed through an exception handling trick. Consider:
struct B { }; // not polymorphic
struct D1 : public B {}; // not polymorphic
struct D2 : private B {}; // not polymorphic
D1 d1;
D2 d2;
template <typename B, typename D>
const B* is_unambiguous_public_base_of(const D* obj) {
try {
throw obj;
}
catch (const B* pb) {
return pb;
}
catch (...) {
}
return nullptr;
}
Then we have
static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");
assert((is_unambiguous_public_base_of<B>(&d1)));
assert(!(is_unambiguous_public_base_of<B>(&d2))); // Notice the negation.
It's worth mentionning that is_unambiguous_public_base_of is far slower than dynamic_cast and (this became more obvious after the renaming mentioned in the update below) always returns a nullptr for downcasts:
B* b1 = &d1;
assert(dynamic_cast<D1*>(b1)); // Requires D1 and B to be polymorphic.
assert(!(is_unambiguous_public_base_of<D1>(b1))); // Notice the negation.
A bit outdated reference on this trick is available in the following links:
Part 1, Part 2 and code
Disclaimer: the implementation of is_unambiguous_public_base_of above is just a draft to make the point and it doesn't handle const and volatile qualifications properly.
Update: In a previous version of this post is_unambiguous_public_base_of was named my_dynamic_cast and this was a source of confusion. So I renamed it to a more meaningful name. (Thanks to Jan Herrmann.)
You could use dynamic_cast.
if (dynamic_cast<DerivedClass*>(ptr)) {
std::cout << "Class is derived from DerivedClass.";
}
Check if class is derived from a specific class (compile time)
You can use std::is_base_of:
#include <type_traits>
....
const bool isBase = std::is_base_of<base, TheOtherClass>::value;
isBase is true if TheOtherClass is derived from base.
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<class T>
void do_it1(T const& t) {
if (std::is_base_of<T,derived1>::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<class T>
void do_it3_impl(T const& t, std::true_type) {
// here t will be of a type derived from derived1
}
template<class T>
void do_it3_impl(T const& t,std::false_type) {
// here t will be of type not derived from derived1
}
template<class T>
void do_it_3(T const& t) {
do_it3_impl(t, std::is_base_of<T,derived1>()); // 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<derived*>(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.
You can do this in several ways. The most common ones as the others have pointed out are dynamic_cast<> and std::is_base_of. The latter is used at compile time, while dynamic_cast<> can be used at runtime.
HOWEVER, dynamic_cast<> will only work if your source class is polymorphic (i.e. has at least one virtual function - it can be a method or its destructor). If not, the compiler will trigger an error.
The compiler will only accept pointers to classes derived from your base class if your library functions takes pointers to the base class. My answer is with a classical approach type safety will handle it. To my experience that kind of type checking is enough. Having 25 years experience in the industry I question the need to do this check. Maybe such a fundamental question is not welcome? I would like to see the justification to having the need to do this kind of upcast. I never have to do that. The opposite, i.e. a down cast I need quite frequently.

boost::is_same with templated base class

I'm puzzled by the following problem. I want to write some trait struct in order to test if a certain class is derived from another. This can be solved with boost::is_base_of<>. However, the base class I want to test against has a free undefined template parameter.
Here is some code example:
template<typename T> class Base {};
class IntDeriv : Base<int> {};
class Foo {};
template< class TestClass >
struct is_derived_from_Base {
// how to create something that does the following and forces the compiler to deduce T
static const bool value = boost::is_base_of< Base<T> , TestClass >::value;
};
int main() {
cout << is_derived_from_Base<Foo> << endl; // should print 0
cout << is_derived_from_Base<IntDeriv> << endl; // should print 1
}
The problem is how to deduce T for Base<T> inside is_base_of.
Is this possible at all? I smell some enable_if but I'm not sure how to put it together.
What you want is possible. The trick used is possible in C++03, but as you didn't specify I will give you the C++11 version (using decltype, not available in C++03):
template<class TestClass>
struct is_derived_from_Base
{
template<typename T>
static std::true_type inherited(Base<T>*);
static std::false_type inherited(void*);
static const bool value = decltype(inherited(new TestClass()))::value;
};
You can see a live version here.
So, how does it works ?
When the struct is instantiated and value is needed, the compiler will get the return type of inherited(new TestClass()). This will call the appropriate function: if TestClass inherits Base<T>, then TestClass* (returned by new) is castable to Base<T>*, T being automatically deduced by the compiler. The return type is std::true_type. If TestClass does not inherits Base<T>, then the other overload is choosen, and the return type is std::false_type. The rest is straightforward: std::true_type::value = true and std::false_type::value = false.
There are still some corner cases:
Using private inheritance results in a compile error. I do not know how to solve it, because I don't know the answer: if A privately inherits B, is A derived from B or not ? (in general, private inheritance is considered as an implementation inheritance). Also note that in this case, A* a = new B(); will not compile.
Using a private constructor prevents the previously explained trick from working correctly. It will result in a compile-time error. Since this defeats the whole point of this method, you will have to find another way for such classes.
Note you have to use it the following way: is_derived_from_Base<Foo>::value, not as you've written (is_derived_from_Base<Foo>).