Inheritance and templates in C++ - c++

I have the following problem with inheritance and templates:
class Base {};
class Deriv : public Base {};
template <class T> class X{};
void f(X<Base>& inst) {}
int main()
{
X<Base> xb;
f(xb);
X<Deriv> xd;
f(xd);
return 0;
}
The program doesn't compile because there is not relation between X<Base> and X<Deriv>. Nevertheless I think it should be possible to do everything that can be done with X<Base> also with X<Deriv>. Is there anything that I could do other than copying the function body of f to a new function void g(X<Deriv>& inst)?

You could just continue using templates:
template<class T>
void f(X<T>& inst) {}
will work for both X<Base> and X<Derived>.
The compiler might duplicate the code (if it is not smart enough), but you don't have to.

Why do you think they should be related? Consider the following:
template<typename T>
class X;
template<>
class X<Base> {
int x;
};
template<>
class X<Deriv> {
double d;
};
They're definitely not interchangeable. So no, there is no relation between those classes and you can't pass one to a function expecting the other. You'll have to do something like make both types inherit from another common type that exposes the interface you need.
Regarding your comment, you can use type traits and static_assert to do what you would do in Java:
template<typename T>
void f(X<T>& inst) {
static_assert(std::is_base_of(Base, T)::value, "Template type must subclass Base");
// body of function...
}

If you need such functionality, then you must template on the type- or overload, as you have said. Alternatively, you might explicitly specialize X such that X<Derived> : X<Base>.

Different instantiations of a template are unrelated types, even if the instantiating template arguments are related. That is, X<A> is not related to X<B> regardless of what the relationship between A and B might be.
Now as of what can be done, it depends on what your template actually is. In some cases you can provide conversions so that the X<Derived> can be converted to a X<Base> for a particular operation. Another alternative is modifying your function to be able to take any X<T> for which T derives from Base (this can be done by creating a template and using SFINAE to disallow calling it with Ts that don't derive from Base. Again, depending on what your template is, you might be able to offer access to the underlying type, in which case the function could take a reference to Base (consider shared_ptr or unique_ptr with the .get() method)
Without a description of what you actually want to get done it is impossible to provide a good alternative.

It depends. Consider the case where X is std::shared_ptr. It would break type safety if std::shared_ptr<Derived> was derived from std::shared_ptr<Base>, but instead there is an implicit value conversion.
However, since you’re passing by reference to non-const, such a value conversion will not help you you directly.
Other possibilities include inheriting from a common interface, and templating your function.

Related

template enforcing unnecessary restriction

Say an Object has a templated TYPE (for a very good reason)
template <typename T> class Object {
};
I want an Object to be able to contain an array of subobjects.
template <typename T> class Object {
vector< Object<T>* > subobjects;
};
However, the subobjects CAN BE OF ANY TYPE. That is, a subobject can be an Object of a different T than it’s parent.
The language is enforcing a restriction that doesn’t need to be there. How do I fix this?
A template is a type-factory. Object<int> and Object<double> are unrelated types.
Object<int> generates one type, and Object<double> generates a different type.
If you want these two types to be related, you can make them related.
struct IObject {
virtual ~IObject() {}
// common interface
};
then
template<class T>
struct Object<T>:IObject {
std::vector<IObject*> subObjects;
};
now your Object<T> has subobjects. All the code knows (statically) is that they are IObjects.
Now, if you want the type T to be runtime determined, you could use std::any (this has type safety issues, sort of; it is "brittle" in that the reader needs to know the exact type that went into it) or std::variant<double, int, std::string> (but here you have to name all of the supported types).
Basically, you are probably using a round peg and a square hole.
You have a problem. You thought templates where the solution. You found a problem with your solution. You looked for a way to make templates work.
The language is enforcing a restriction that doesn’t need to be there. How do I fix this?
The language isn't enforcing anything. You wrote a template with one type parameter, so that parameter can only take one value at a time.
However, the subobjects CAN BE OF ANY TYPE. That is, a subobject can be an Object of a different T than it’s parent.
If you mean each Object<T> can have children of a single different type U != T, just write
template <typename T, typename U> class Object {
vector< Object<U>* > subobjects;
};
If you mean each object can have children of a variety of instantiations, you either need some form of type erasure (eg. std::any), or polymorphism.
In either case, you need to give some thought to what you're going to do with these things you don't know the concrete type of. How will you use them? This is the information needed to choose the appropriate mechanism.
Using #WayneVanderLinde's comment:
struct Object{
vector<Object*> subobjects;
};
template<typename T> struct TObject : public Object {};
you can now create
TObject<int> i;
TObject<double>* d = new TObject<double>();
i.subobjects.push_back( d );

Is std::iterator inherints from a sort of auto_ptr?

I am a beginner in STL. I'm trying to code a toystl to learn STL. When I code about iterator, I'm puzzled if I should code a simple auto_ptr first and inherint from it.
I wrote a base class called iterator. And now it works like this,
struct iterator{};
template <class T>
struct vector_itorater: public toystl::iterator<toystl::random_access_iterator_tag, T>{};
If i need another base class works like a "auto_ptr"? just like this
// firstly define a sort of auto_ptr as base class
struct auto_ptr{};
// secondly inherint from auto_ptr
template <class T>
struct vector_itorater: public auto_ptr{};
Does this work? Or does STL do it like this?
I think you mixed up runtime polymorphy and compile time polymorphy. When the compiler instantiates a template, it cares about its visible interface of the concrete object. It does not care if this object has a inheritance relationship with other classes, it will pass as long as the concrete object can be used within the concrete context.
template <class C>
void foo(const C& bar)
{
// at the time of writing we don't know anything of C,
// only that it has a callable baz member (either a
// member function or a member with a call operator).
// This works, since the compiler knows the exact type
// during template instantiation, but we don't have to
// care in advance.
bar.baz();
}
struct X
{
void baz() const;
};
void grml()
{
X x;
// The compiler fills in X as the template type
// parameter for us. So the compiler creates a
// void foo<X>(const X&) function for us.
foo(x);
}
In this example when the compiler sees the template, it has no clue how this template will be called later. Only once the template gets instantiated (used), the compiler then will check if the passed type is suitable for this template.
Here it is not needed to have a common base class to derive every possible implementation from. The STL uses templates in order to avoid to use such base classes, since they give you a burden on your design later, and if you have virtual members in the base to override, you can get a serious performance penalty.

Template class with no use of template argument

I have stumbled many times on classes defined like
class PureVirtualClass
{
virtual int foo() = 0;
virtual bool bar() = 0;
}
template <class T> class ImplClass : public virtual PureVirtualClass
{
virtual ~ImplClass(){};
int foo() { return 42;}
bool bar() { return true;}
//several other method having nothing to do with T
}
This "design" appears so often I want to think the original developer knew what he was doing by defining ImplClass as template class but without any reference to the template argument T anywhere. My own c++ template knowledge is kinda limited.
Is there a benefit to this or is it just a confused programmer?
There can be a benefit for classes being templated but not depending on the argument. Most often you see such things to define (empty) tag-structures for template metaprogramming:
template <class X>
struct some_tag {};
The benefit of classes like yours in general is that while you have the same functionality in each class, they are different classes and you can't copy one into the other, i.e. an object of type ImplClass<int> is not compatible with another object of type ImplCalss<float>.
There are many useful cases of the idea mentioned by Arne. For instance, looking at Very basic tuple implementation, this is how a single tuple element is defined:
template <size_t N, typename T>
class TupleElem
{
T elem;
public:
T& get() { return elem; }
const T& get() const { return elem; }
};
It is templated on N, without depending on it. Why? Because the tuple implementation
template <size_t... N, typename... T>
class TupleImpl <sizes <N...>, T...> : TupleElem <N, T>...
{
//..
};
derives multiple such elements, each with a unique N, serving as an identifier. Without it, TupleImpl would be deriving the same class twice, had two element types been identical within parameter pack T.... Neither random access to elements would work in this case (via an explicit call of function get() of the appropriate TupleElem base class, which would be ambiguous), nor empty base optimization (via specializing TupleElem for empty types T to not have a data member of type T).
This is a real use case, and exactly how std::tuple is implemented by clang. Of course, a class like TupleElem would be a hidden implementation detail, and not part of the interface. For instance, gcc follows an entirely different recursive class design.
In general, you will need to study the context where classes are used to understand the intent of the designer.
maybe that developer simply is too lazy to split the classes into .h and .cpp files?
Without using templates, linker errors would occur if the classes are used in multiple compilations units. When using templates, the linker usually discards duplicate instantiations of a template at link time (or handles the problem in a different way).
While this may be an answer to "why did the developer do this", I would not recommend this if the question was "when should I introduce template arguments which are never used" (see the other answers for this). Even though it is annoying to split code into .h and .cpp (especially when used to languages like Java or C#), it's the usual C++ way. And it is definitely easier to read/understand than using templates only for this purpose. Also, it makes the use of the classes less readable.

Partial specialization syntax confusion

To define a specialization that is used for every Vector of pointers and only for
Vectors of pointers, we need a partial specialization:
template <class T> class Vector <T *> : private Vector<void *> {
public:
typedef Vector<void*> Base;
Vector(): Base() {}
explicit Vector(int i) : Base(i ) {}
T *& elem(int i ) { return static_cast <T *&> (Base::elem(i)); }
T *& opeator[](int i) { return static_cast <T *&>(Base::operator[](i )); }
//...
};
This definition has me in a tizzy. This is related to partial specialization but i don't understand the syntax. private Vector<void *> definition part looks like a parent class to me.
Why not specify Vector <void *> in template <class T> class Vector <void *>.
It would be great if anybody can breakdown the definition part. (sorry if its too much to ask)
Forget about the inheritance, which has nothing to do with the problem at hand.
Partial specialization means that you make a new template from an existing one which is more specialized, but still generic, by matching a more restrictive pattern. The general pattern of your example is like this:
template <typename T> class Foo; // primary template
template <typename U> class Foo<U*>; // partial specialization
template <> class Foo<fool>; // full specialization
The first line is the primary template and matches everything that is not matched by a more specialized form. The third line defines an actual type (not a template!) Foo<fool> (for some given type fool). The middle line, on the other hand, is still a template, but it only matches a type of the form T = U *, i.e. a pointer:
Foo<char> x; // uses primary template with T = char
Foo<fool> y; // uses full specialization (nothing to be matched)
Foo<int*> z; // uses partial specialization, matching U = int
About the Vector<void*>: It just turns out that the author chooses to define the partially-specialized Vector<U*> as deriving from a fixed class Vector<void*> (which would have to be fully specialized elsewhere).
Your question is about template specialization, and that's what's going on here.
This is a template class definition of a Vector<T> being specialized for a pointer type T. Presumably, you've defined the Vector<T> template elsewhere, so this code is only specializing it for the circumstance where T is a pointer. Hence the Vector<T*>.
Since it is a specialization, the Vector<T*> derives from the Vector 'base-template', which is a Vector<void *>. The other code, which isn't detailed in your example, would handle specifics of working with a pointer type as the contained data.
Basically, this is making the members of Vector<Ptr>, for any pointer type, forward to Vector<void*> (using a combination of inheritance and explicit base calls plus casting). This prevents the compiler from making many identical versions of the same code, differing only by the pointer type, possibly saving space in the final executable (although most linkers are smart enough to combine identical functions, see for instance "COMDAT folding")
This is problematic according to the Standard because the pointers don't have the same alignment restrictions. Not all object pointers necessarily have the same size in a conforming implementation. In fact, I'm very surprised that the compiler accepts static_cast<T*&>(a_void_ptr) at all. Static casting between void* and T* is allowed of course, but this deals with reference-to-pointer types, which are unrelated. It should require reinterpret_cast.
It seems that the author of the code wants to exploit the fact that the code for different pointer types is identical. It is probably just a premature optimization to reduce code size, or "code bloat". The idea is most likely that each new pointer type will only add a layer of static_cast to the void pointer code.

Hold any kind of C++ template class in member variable

I have got two classes.
The first class (A) is builded with an template.
template <class T>
class A
{
public:
T value;
};
The second class (B) should have an object of class A as member variable. Like this:
class B
{
public:
A<int> value;
};
But now i want to use any kind of template-class in class A. Not only int.
Apparent I can't declare a (member-)variable which contains any kind of a class.
So, I need something like this:
class B
{
public:
A<*> value;
};
Is there any (clean) solution for this problem?
-- Greeting from Germany, Bastian
You cannot have a single class B with "any" member object, because B has to be a well-defined class, and A<T> is a different type for different types T. You can either make B a template itself:
template <typename T>
class B
{
A<T> value;
};
or you can take a look at boost::any, which is type-erasing container for arbitrary types (but making use of it requires a certain amount of extra work). The any class only works for value types, though, it's not completely arbitrary.
The simplest solution would be to make all A variants ineherit from a common interface, even if it's empty :
class IA{}
template <class T>
class A : public IA
{
public:
T value;
};
class B
{
public:
IA* value;
};
Now, the associated costs:
interactions with value are limited to the IA interface;
if you try to cast to get the real type, that mean that you know the real type, so it's of no use and make A type a parameter of B becomes really easier to use.
there are runtime costs associated to runtime inheritance
Advantage :
it's easily understood by other developers
it naturally limit the types possible to some specific ones
it don't use boost (sometimes, you just can't)
So to do better there are other less simple solutions but that are simple enough to be used :
If you can use boost, boost::any, boost::variant and boost::mpl might be base of solutions.
Boost any can be used as a safe replacement to void*. The only problem with this is that you can have ANY type, like if the type was a template parameter of the B class.
Boost variant might be used successfully if you know all the types that A can be.
MPL might be helpful if you just want to set a list of possible types and make sure your members apply only to them. You can do a ton of things with MPL so it really depends on your exact needs.
You've got two choices, I think. The first is to parameterize your class over the type parameters of the instance variables:
template <class T> struct B
{
A<T> value;
};
The other option is to declare value as a void* pointer. (But that's probably not what you want).
yes, it's already been done. boost::any.
I think it helps to understand, that templated classes create an entirely new and seperate class for every type you use with it. For instance, Vector<int> and Vector<float> are as separate as the classes VectorInt and VectorFloat.
For class B, you are basically asking that the value variable either be A<int> or A<float>, which is the same as saying you want value to either be a "A_int" or "A_float". And to accomplish that you... well, use another template!