Recursive inheritance with variadic templates and inherited parameter problems - c++

If I use a chain of inheritance like the following example I could use vars from the deepest base without any problems:
class A { public: int x; };
class B : public A { };
class C: public B { public: void Do() { cout << x << endl; } };
If I do the same with recursive variadic template classes I could not access my vars. Any idea how to access the vars and why I could not see my vars?
template <class ...Parms>
class Example;
template <class Head, class ...Parms>
class Example<Head, Parms...>: public Example<Parms...>
{
};
template <>
class Example<>
{
public:
int x;
};
template <class ...Parms>
class Last: public Example<Parms...>
{
void Do() { cout << x << endl; }
};
Compile fails before any instance of the class is instantiated!

x is a dependent name in this case, so you must access if as this->x (or bring it into scope by putting a using declaration in your class definition:
using Example<Params...>::x;
EDIT
The reason for this is discussed in [temp.res] in the standard. Basically: when the compiler is parsing your template, it sees just x. It has no way of knowing that x depends on the template's parameters (which it does in your case, because it comes from a base class which depends on them). Therefore, the compiler tries to resolve x using what it knows when parsing the template, and fails.
Writing this->x indicates that x refers to a member of the class; since a base class of your particular class depends on template parameters, the compiler knows it cannot resolve x when parsing the template, and will postpone the resolution until the template is instantiated. At that time, the template arguments are known.
The same holds true for using Example<Params...>::x;. That also tells the compiler that x depends on template parameters, and its resolution must be postponed to instanitation.

Related

Deriving a class from a class template

I am new to C++. During my learning phase I encountered with below issue.
I am trying to derive a class stack from a class template Queue.
Compiler throws below error in constructor of stack
..\src\TrainingDay2.cpp:44:3: error: 'b' was not declared in this scope
b=a;
Please help to find out the root cause.
#include <iostream>
using std::cout;
using std::endl;
template<class T> class Queue //Base class
{
private:
T ArrQueue[20];
protected:
T* a;
T* b;
public:
Queue() { cout<<"QUEUE CONST "<< endl; }
void push(T x);
void pop(void);
};
template <class T>
class stack :public Queue<T> // Derived class
{
public:
stack():Queue<T>() {
b=a;
}
void pop() {
b--;
}
};
int main()
{
stack<int> S;
return 0;
}
Because the base class is a template, whose instantiation depends on a template parameter of the derived class, and you're trying to name a member of the base class, two-phase lookup mandates that you write this->b, not b.
(And that default constructor call is not needed.)
stack()
{
this->b = this->a;
}
void pop()
{
this->b--;
}
(live demo)
Welcome to C++… :P
[C++11: 14.6.2/3]: In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [..]
The reason is that inside a template, two-phase name lookup rules apply:
Names which do not depend on template parameters are looked up (=resolved) when the template is defined (=parsed).
Names which do depend on template parameters are looked up when the template is instantiated (when you provide the template arguments).
Base classes which depend on template parameters are only searched during name lookup at instantiation time.
The reason for this two-phase lookup is that until the template arguments are known, the compiler cannot know what the definition of the base class (or other dependent construct) will be. Remember that template specialisation exists.
You need to somehow tell the compiler that the name b is dependent. You basically have three ways to do that:
Prefix the name with this->; since you're in a class template, all your members depend on template parameters implicitly:
this->b = a;
Use full qualification for the name. This will make the dependency on template parameters explicit:
Queue<T>::b = a;
Put a using declaration into your class to inform the compiler that the name comes from a dependent base class:
template <class T>
class stack :public Queue<T> // Derived class
{
protected:
using Queue<T>::b;
public:
stack():Queue<T>()
{
b=a;
}
void pop()
{
b--;
}
};
In a template definition, unqualified names will no longer find members of a dependent base (as specified by [temp.dep]/3 in the C++ standard). For example,
You must make the names dependent, e.g. by prefixing them with this->.
gcc-problem-using-a-member-of-a-base-class-that-depends-on-a-template-argument
And yes, it can be valid in VS.

Accessing base member functions in class derived from template class [duplicate]

This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 8 years ago.
I am developing a library at my work and I have designed a complicated inheritance that includes template classes and deriving from them.
My problem is that a base template class has virtual overloaded operator that takes 2 arguments and returns some value. In base class this operator is implemented and most of derived classes does not reimplement this operator.
Some other class uses derived classes for some work and make use of their operator member function. Everything works just fine as long as derived class has no other overloaded operator, even with different number of arguments. If one does then the base class operator is not accessible using it as object() because compiler can not find proper member function (complains about argument count missmatch).
It does not matter wether default template arguments for base class was specified or not. Also order of definitions of derived classes does not change which operator cause the problem (it is always SpecificDerived class).
Below I present simplified problem.
[EDIT] Example was simplified
Base Class definition:
template<class ret_t>
class TemplateBase2
{
public:
virtual ~TemplateBase2()
{
}
virtual ret_t memberFunc(ret_t x)
{
return x * 2;
}
};
User of derived classes definition:
template <class worker, class ret_t>
ret_t gobble(worker w, float f)
{
return w.memberFunc((ret_t)f);
}
Derived class:
class SpecificDerived2: public TemplateBase2<float>
{
public:
float memberFunc()
{
return 3.14;
}
};
Main function:
#include <iostream>
#include "TemplateBase2.h"
using namespace std;
int main()
{
SpecificDerived2 sd2;
cout << "sd2: " << gobble<SpecificDerived2, float>(sd2, 3.14f) << endl;
return 0;
}
Compiler exits with error claiming that there is no matching function for call to 'SpecificDerived2::memberFunc(float)' from gobble function. Problem exists only when either derived or base class has two overloaded functions of the same name, but different arguments.
I am using MinGW32 4.8.1 with c++11 support.
When a class template derives from a base class template, the base members are not visible in the derived class template definition. (This makes sense; until you specialize, there is no class, and so there are no members. Explicit specializations can always change the meaning of any given template class.)
In other words, the base template member names are dependent names and not looked up in the first phase of template definition lookup.
There are three ways to get around this. Let's make it concrete with a quick example:
template <typename T> struct Foo
{
int data;
using type = const T &;
void gobble() const;
template <int N> void befuddle();
};
template <typename T> struct X : Foo<T> { /* ... */ };
Now in the context of the derived class template definition, you can...
Qualify the name:
Foo<T>::data = 10;
typename Foo<T>::type x;
Foo<T>::gobble();
Foo<T>::template befuddle<10>();
Use this:
this->data = 10;
this->gobble();
this->template befuddle<10>();
(This doesn't work for type names names.)
Use a using declaration:
using Foo<T>::data;
using Foo<T>::gobble;
using type = typename Foo<T>::type;
data = 10;
gobble();
(This doesn't work for template names.)
Update: After your edit, the question is entirely different. Templates don't play a role at all here, since the problem doesn't contain templates, only classes. What's happening is the simple fact that member functions in a derived class hide member functions of the same name in base classes, so the presence of SpecificDerived2::memberFunc hides the base member function. The simple solution is to unhide base members of the same name with a using declaration:
class SpecificDerived2 : public TemplateBase2<float>
{
public:
using TemplateBase2<float>::memberFunc;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
float memberFunc()
{
return 3.14;
}
};

Inheritance of template classes in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ Inherited template classes don't have access to the base class
I'm experiencing problems with templates and inheritance. Simply, I have a template class which I want another template class to inherit from. I don't understand why members of base class are not visible within deriving class? Though without using templates everything works as expected. For example:
template <typename T>
class Foo
{
public:
T x;
T y;
void doX(){ x = x+1; }
void doY(){y++;}
protected:
T a;
T b;
void doA(){a++;}
};
template <typename T>
class Bar : public Foo<T>
{
public:
void doX(){x++; y++;} // ERROR
void doY(){x++; y++;} // ERROR
void doA(){a++;b++;} // ERROR
};
These variables are dependent names (read The Dreaded Two-Phase Name Lookup for details), so you need to use this as:
void doX(){ this->x++; this->y++; }
Usually this-> is not required as it is implicit. But here it is required. Actually explicit this-> tells the compiler to look up the name in the second phase when the base class is instantiated, as this case uses two-phase name lookup mechanism.
Or you could qualify them with base class as:
template <typename T>
class Bar : public Foo<T>
{
typedef Foo<T> base; //add this friendly typedef!
public:
void doX(){ base::x++; base::y++;}
//...
};
In this case, the fact that the names cannot be looked-up untill base (which is a typedef of Foo<T>) is instantiated, becomes more obvious (to humans eyes) in my opinion.
If the base class depends on a template parameter, then its members aren't directly available in the derived class definition. Until the template is instantiated, the compiler doesn't know what the base class will contain, and so it won't look up any names from there.
You can force it to treat the names as members by qualifying them:
void doX(){this->x++; Foo<T>::y++;} // OK: both forms specify that it's a member
Write this->x, this->y instead of x, y in derived class functions.
Try referring to the variables using the base class scope:
Foo<T>::x
or use this
this->x

C++ template class specialization: why do common methods need to be re-implemented

In the sample:
#include <iostream>
using namespace std;
class B
{
public:
virtual void pvf() = 0;
};
template <class T>
class D : public B
{
public:
D(){}
virtual void pvf() {}
private:
string data;
};
template <>
class D<bool> : public B
{
public:
D();
virtual void pvf(){ cout << "bool type" << endl; }
};
int main()
{
D<int> d1;
D<bool> d2;
}
I get the following error:
test.cpp:(.text+0x1c): undefined reference to `D<bool>::D()'
Note that the reason I don't just specialize the D() by itself is I want to eliminate the need for string D<T>::data in the D<bool> case.
Why do I need to re-implement D() in D<bool>? Seems like there should be a way for me to tell the compiler to use the version from D<T>.
Is there any way to do a simple specialization like this without having to re-implement methods?
Each specialisation of a class template gives a different class - they do not share any members with each other. Since you've explicitly specialised the entire class, you don't get any of the members from the template, and must implement them all.
You can explicitly specialise individual members, rather than the entire class:
template <> void D<bool>::pvf(){ cout << "bool type" << endl; }
Then D<bool> will still contain all the members of the class template that you haven't explicitly specialised, including the default constructor.
No, there is not.
Specialization is behaving very differently than inheritence. It has no connection to the generic template version.
When you use/instantiate a template, the compiler will create a new type name, and then look for how this type is defined. When it finds a specialization, then it takes that as the definition for the new type. When it does not, it takes the generic template and instantiates it.
Therefore they have no connection, and you are just writing an entirely new class, just with a special name for the compiler to find in case of someone using/instantiating the template to find it under that name.
The problem is your erroneous assumption that there is anything common between D<A> and D<B>. Template instances are types, and two different instances are two different types, end of story. It only so happens that instances of the same template have formally similar code, but with specialization you can define any type you like. In short, every type that you define explicitly is entirely independent, and there is no commonality across specialized template instances, even if they happen to have the same name.
For example:
template <typename T> struct Foo
{
T & r;
const T t;
void gobble(const T &);
Foo(T *);
};
template <> struct Foo<int>
{
std::vector<char> data;
int gobble() const;
Foo(bool, int, Foo<char> &);
};
The types Foo<char> and Foo<int> have nothing to do with one another, and there is no reason why any part of one should have any use inside the other.
If you want to factor out common features, use private inheritance:
template <typename> struct D : private DImpl { /* ... */ }
You need to reimplement it because D<T> and D<bool> are totally unrelated classes (they just happen to "share the name"). That's just how templates work.
If you want the classes to share construction code, just put that code inside B::B (i.e. the same thing you do every time you want to reuse code in different branches of the same hierarchy: move the code up and let inheritance handle the rest).
Consider that D<T>::D() will be responsible for default-constructing string data, and that D<bool> doesn't have any such member. Clearly there is no way to use the same emitted code in each case.
However, if your default constructor doesn't do anything (in either version here), just omit it and allow the compiler to do the work.

Declaring an instance of an explicit specializtion of a template within a regular class

I can't get this to compile at all. I may not be possible but I don't know why it should not be.
class A {
template <typename T>
class B {
int test() { return 0; }
};
//template <> class B<int>; <-with this, namepace error
B<int> myB_;
};
template <> class A::B<int> {
int test() {
return 1;
}
};
As it appears the compiler complains "The explicit specialization "class A::B" must be declared before it is used."
If I try to provide the froward declaration in the commented line, the compiler complains
"The explicit specialization "B" must be declared in the namespace containing the template."
We use 2 different compilers here. This error is from IBM's "xl" compiler on AIX but I get similar errors with different verbage when compiling on our Sun systems.
It seems like a catch-22.
Obviously, this is a highly contrived, simplistic example but, it represents the problem.
I want to define a template class within a class because the template class is only relevent to the containing class. There should be no access to the template from outside the class.
Am I missing something?
You are correct. This is not possible to do (as far as I know). Your member declaration causes an implicit instantiation before the explicit specialization was declared. But how would you want to declare it? You cannot do that in class scope. Others have felt that this is an ugly restriction.
You could work around this by making the class member a pointer. This would not need to implicitly instantiate the class at that point, but rather at the point where you create the object in the end. I realize that this is an ugly work around. So better find other ways to do this.
For instance partial specializations are allowed in class scope. So you could add a dummy template parameter, then you can specialize this in the class before the member declaration. Likewise, i find this ugly, but it would not disturb things that much, I feel.
You could work around the issue by using an unnamed namespace for privacy:
namespace {
template <typename T>
class B {
int test() { return 0; }
};
template <> class B<int> {
int test() {
return 1;
}
};
}
class A {
B<int> myB_;
};
This will compile, but if A needs to be visible outside this compilation unit, you'll need more elaborate machinery (e.g., interface and factory or Pimpl).
B is not a template class and you are trying to specialize it. That is the cause for the error. You can check these two errors C2913 and C3413.
Is this what you are looking for?
class A
{
template<class T>
class B
{
inline int test()
{
return 0;
}
};
A::B<int> myB_;
};