Why can I omit the template parameter specification in some cases? - c++

I have a question as I cannot explain why something works where I probably have made a mistake. Maybe somebody kind can help me to improve my C++ culture by explaining to me why this is so.
For better transparency I simplifiy the code quite a bit.
I have a template virtual class that is like this:
template<class Node>
class tXmlNode
{
public:
tXmlNode();
virtual ~tXmlNode();
protected:
Node* node;
}
;
From this I derive several classes.
Mostly I derive from it another template class such as this one:
template<class Part>
class tXmlMove : public tXmlNode<Part>
{
public:
tXmlMove(Part* part);
~tXmlMove();
protected:
int n_translate;
};
with this implementation (reduced to the constructor):
template<class Part>
inline tXmlMove<Part>::tXmlMove(Part* part) : tXmlNode<Part>(part)
{
//do some construction
}
;
As you can see I delegate some part of the construction to the parent class constructor. Works fine.
Now I have another derived class but which is derived from a specialized parent class (the specialisation is a self-specialisation but from other classes with similar specialized parent it works exactly as for this one):
class tXmlCaseDefinition : public tXmlNode<tXmlCaseDefinition>
{
public:
tXmlCaseDefinition();
tXmlCaseDefinition(const pugi::xml_node& parent);
~tXmlCaseDefinition();
protected:
int n_shapes;
}
;
(I guess it is due to the specialization that I do not need to construct this class as a template class.)
Its not-default constructor is implemented as follows:
nXml::tXmlPart::tXmlPart(
const pugi::xml_node& parent,
const int npos) : tXmlNode(parent, npos), this_id(""), this_type(""), description("")
{
}
;
As you can see I did not delegate to the parent constructor by using tXmlNode<tXmlCaseDefinition>(parent,npos) but simply tXmlNode(parent,npos). I didn't pay attention to that and it works for some mysterious reason. I simply cannot understand why. Can somebody explain?
Also do I need to use tXmlNode<Part>(part) or can I use tXmlNode(part) instead for classes not derived from the specialized parent class or is this only possible when I have a spezialized parent?
Thank you very much!

Within the definition of a template class (more formally, the "current instantiation"), there is something called an injected-class-name, which is simply the name of the template sans arguments. For example:
template<class T>
struct Foo
{
Foo* ptr; // refers to Foo<T>
};
When you derive from a templated class, the base class' injected-class-name is inherited. Therefore you can also refer to the base class sans template arguments (assuming the name is accessible; some ancestor didn't privately inherit from it):
template<class T>
struct Base
{
};
struct Derived : Base<int>
{
Base* ptr; // refers to Base<int>
};
cppreference does a decent job of summarizing all the standardese here (Refer to [temp.local], [basic.lookup], and [basic.scope.class])

Related

Calling base class method in derived class without specifying base class name

When overriding a C++ virtual method, is there a way to invoke the base class method without specifying the exact base class name, in a similar way that we can do it in C# with the "base" keyword? I am aware that this could be in conflict with multiple inheritance, but I wonder if more modern versions of C++ have introduced such a possibility.
What I want to do is something like this:
class A
{
public:
virtual void paint() {
// draw something common to all subclasses
}
};
class B : public A
{
public:
virtual void paint() override {
BASE::paint();
// draw something specific to class B
}
};
I know that in B::paint() we can call A::paint(), I just want to know if there is a more "generic" way to call the base method without referring explicitly to class A.
Thank you in advance.
Andrea
No, there is no fancy keyword to access to the base class.
As some comments already mentioned, some proposals have been rejected by the standard committee.
Personally, in some contexts, I opt for a typedef/using directive; especially when my hierarchy has templated classes.
For instance:
template <typename T>
class A {};
template <typename U, typename T>
class B : public A<T> {
private:
using Base = A<T>;
public:
void foo() {
// Base::foo();
}
};

C++ template declaration with inheritance list

Is it possible to declare a templated class in C++ along with the classes it inherits from? Basically I want to give the compiler a hint, that my templated class will always inherit another at declaration time.
Maybe some code will clear up why this is a problem for me:
template<typename T>
class GrandparentClass
{
public:
T grandparentMember;
};
//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{
};
// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;
// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;
template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
ParentClass()
{
grandparentMember = 5;
}
};
template <typename T>
class ChildClass : public ParentClass<T>
{
public:
void foo()
{
std::cout << grandparentMember << "\n";
}
};
Also, I cannot use C++ 11.
EDIT:
I found an easy way out of this:
template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
ParentClass() { ParentClass::CompilerError(); };
};
Just do not define CompilerError() method in the class and everything's fine.
A class declaration is only really useful for non-value variable declarations, like pointers and references. You can't access the class members or even instantiate it, though. Even if you knew that a declared class inherits from some other one, you still wouldn't necessarily be able to utilize that information in any way.
As such, it's only important for the compiler to know what the class inherits from once it learns its full definition.
After clarification in comments: if you want to prevent instantiation of a class template with some types, its definition is the place to do it. A simple static_assert inside the class body will do the trick; Boost.StaticAssert or older SFINAE tricks will do the job for pre-C++11 code.
If you are happy with delaying the error to link-time, rather than compile time, you can declare all the member functions of parent in parent.h, provide definitions in parent.cpp, and explicitly instantiate the finite list of classes that you want.
Parent.h
template<typename T>
class ParentClass : public GrandparentClass<T>
{
ParentClass();
};
class ParentClass<int>;
class ParentClass<long int>; // or whatever
Parent.cpp
template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}

How to force use of curiously recurring template pattern in C++

I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};

Taking template class as a general argument, without specifying template arguments

I've got a fairly unique situation.
I've got a structure resembling the following code, where a class template inherits from its own template argument, which may be a certain BaseClass, or any of its subclasses.
class BaseClass {
...
virtual void BaseMethod();
};
class DerivedClass {
...
virtual void BaseMethod(); // DerivedClass Overrides some of baseclass's methods
void DerivedMethod(); // And it has a few of its own
};
template <class T>
class ClassTemplate : public T {
...
// Some validation to ensure that this class template extends
// either BaseClass or one of its derived classes
void ValidateTemplate(const BaseClass& c) {}
...
}
The point where this becomes tricky is when I want to take a template class argument that is templated after the baseclass, or one of its subclasses:
void func(ClassTemplate& c) { ... c.BaseMethod(); }
Of course, this doesn't compile as its missing its template arguments. However, I'm looking for a solution that will function like the following, without having to actually specify the following function overloads:
void func(ClassTemplate<BaseClass>& c) { ... c.BaseMethod(); }
void func(ClassTemplate<DerivedClass>& c) { ... c.BaseMethod(); }
On top of that, one of my other classes contains a list of ClassTemplate pointers:
class ClassWithList {
std::list<ClassTemplate<BaseClass>*> l;
...
}
With the above, I want the list l to contain both ClassTemplate<BaseClass> objects, and ClassTemplatE<DerivedClass> objects. This has the same root problem - hoping that the latter could be interpreted as the former, as is the case for most implicit conversions in C++. Is this particular kind of conversion possible to do with templates? Or is there an alternate workaround?
Notes:
In func, none ofDerivedClass's functions are used - just like if I had taken a BaseClass argument, I want to be able to access its public members.
However, it is important that I don't take BaseClass as an argument. This is because I need to access members of the ClassTemplate object, which are unique to ClassTemplate itself.
Additionally, I can't resort to using multiple inheritance (Have DerivedClass subclass both ClassTemplate and BaseClass) as this will result in diamond inheritance, thus creating an inheritance hierarchy too complicated for simple virtual inheritance.
From your description, it sounds like you want a function template:
template <typename T>
void func(ClassTemplate<T>& c) { ... c.BaseMethod(); }
For handling the list case, one option is to have a third class that you use as the interface:
struct ClassTemplateBase {
virtual void doSomething() = 0;
};
template <class T>
class ClassTemplate : public T, public ClassTemplateBase {
// ...
}
then you can have a std::list<ClassTemplateBase *>. This avoids the diamond inheritance issue.

How to call a method from base class where the base class is a template parameter

i have a c++ class like the below one working at vc++ , but doesnt work anymore in linux gcc 4.7. And i have no idea how to make it work again.
test.h
template<typename a>
class test: public a
{
public:
void fun();
};
test.cpp
template<typename a>
void test<a>::fun()
{
template_class_method(); <-- this is a public method from template_class
}
template class test<template_class>;
template_class.h
class template_class {
public:
template_class();
virtual ~template_class();
void template_class_method();
};
template_class.cpp
#include "templateclass.h"
template_class::template_class() {
// TODO Auto-generated constructor stub
}
template_class::~template_class() {
// TODO Auto-generated destructor stub
}
void template_class::template_class_method() {
}
You need to qualify it with the base class name as:
a::template_class_method();
The qualification a:: is necessary because template_class_method exists in a. The C++ rule is that if the base is a class template or template argument, then all its members are not automatically visible to the derived classes. In order to help the compiler to find the member, you need to tell it to look for the member in the base class, for which you need to qualify the member which is of the form of base::member_function() or base::member_data.
In your case, since the base is a, and the member is template_class_method, so you have to write this:
a::template_class_method();
Note that such a base class is called dependent base class since it depends on the template argument.
I don't know why #Karthik T deleted the answer, but that answer was on the right path. You have several options
Use qualified name a::template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
a::template_class_method();
}
};
Use class member access syntax this->template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
this->template_class_method();
}
};
Make the base class method visible through using-declaration
template<typename a>
class test : public a
{
public:
using a::template_class_method;
void fun()
{
template_class_method();
}
};
Note that the first method will suppress the virtuality of template_class_method (in cases when it is virtual), so it should be used with caution. For this reason, method number 2 is preferred, since it preserves the natural behavior of template_class_method.
Your comment stating that this->template_class_method() "doesn't work" is unclear. It works without any problems. Moreover, as I said above, this is in general case a better option than using a qualified name.