I have a class (Queue) which inherits from a class named Stack.
it goes like this:
template <class T> class Stack
{
public:
virtual const T pop();
LinkedList<T> lst;
};
template <class T> class Queue : public Stack<T>
{
public:
virtual const T pop();
};
template <class T> const T Queue<T>::pop()
{
const T val = lst[0];
return val;
}
The compiler says "lst undecleared"...why?
Because lst is a member of the base class Stack<T> which is a dependent type on T. The compiler can't check dependent types until the template is fully instantiated. You have to let the compiler know that lst is part of such base class by writing Stack<T>::lst.
As its mention in comments, this->lst is also a viable solution. However, people are likely to remove the this as seen unnecessary. Stack<T>::lst seems more explicit in this way.
Try this->lst instead of lst.
Related
I can't seem to call a method of a base class without scoping to the base class, and it seems that this is because I have overloaded the method. If I do not overload the method then the compiler doesn't complain. Here's an example of what I'd like to do:
struct BaseClass {
template <typename T> T& foo(T& t) {
return t;
}
};
class ChildClass: public BaseClass {
public:
// The presence of this template causes compiler confusion
template <class T> T& foo(T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
// But if I scope this as BaseClass::foo(...) it's all good
return foo(t);
}
};
int main() {
int t = 1;
ChildClass c;
c.bar(t);
}
If in bar(...) I call BaseClass::foo(...) the compiler does not complain, but I don't see any ambiguity here and so I'm confused as to why I'd need to do this.
When the compiler tries to match a function name with a function, it does so in two steps. In the first step it finds all the functions that match the given name. If it finds more than one function, it tries the logic of overload resolution to find the best matching function.
In the first step, if the compiler finds a name in the class, it stops looking for functions of the same name in base classes. In your case, since it finds a foo in ChildClass, it stops searching for functions named foo in BaseClass. However, the only matching foo does not match the call and the compiler reports an error.
How to resolve the problem:
Use the method you described in your post. Call BaseClass::foo(...).
Bring all the foo from BaseClass into the scope of ChildClass.
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
return sizeof(foo(1, t)); // Should work.
}
};
From the C++ standard 3.3.10 paragraph 1 :
A name can be hidden by an explicit declaration of that same name in
a nested declarative region or derived class
ChildClass::foo shadows the definition of BaseClass::foo. All you need to bring it into scope is a using directive:
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl);
};
You need a using, like:
using BaseClass::foo;
I can't seem to call a method of a base class without scoping to the base class, and it seems that this is because I have overloaded the method. If I do not overload the method then the compiler doesn't complain. Here's an example of what I'd like to do:
struct BaseClass {
template <typename T> T& foo(T& t) {
return t;
}
};
class ChildClass: public BaseClass {
public:
// The presence of this template causes compiler confusion
template <class T> T& foo(T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
// But if I scope this as BaseClass::foo(...) it's all good
return foo(t);
}
};
int main() {
int t = 1;
ChildClass c;
c.bar(t);
}
If in bar(...) I call BaseClass::foo(...) the compiler does not complain, but I don't see any ambiguity here and so I'm confused as to why I'd need to do this.
When the compiler tries to match a function name with a function, it does so in two steps. In the first step it finds all the functions that match the given name. If it finds more than one function, it tries the logic of overload resolution to find the best matching function.
In the first step, if the compiler finds a name in the class, it stops looking for functions of the same name in base classes. In your case, since it finds a foo in ChildClass, it stops searching for functions named foo in BaseClass. However, the only matching foo does not match the call and the compiler reports an error.
How to resolve the problem:
Use the method you described in your post. Call BaseClass::foo(...).
Bring all the foo from BaseClass into the scope of ChildClass.
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl) {
return t;
}
template <class T> int bar(T& t) {
return sizeof(foo(1, t)); // Should work.
}
};
From the C++ standard 3.3.10 paragraph 1 :
A name can be hidden by an explicit declaration of that same name in
a nested declarative region or derived class
ChildClass::foo shadows the definition of BaseClass::foo. All you need to bring it into scope is a using directive:
class ChildClass: public BaseClass {
public:
using BaseClass::foo;
template <class T> T& foo(int baz, T& t, int szl);
};
You need a using, like:
using BaseClass::foo;
I am trying to use templates for a nested class. I am not sure how to access the class type of the inner class from another class.
Sample Code below.
// I have a List class that can accept any type. It has an inner class
template <class T>
class List
{
public:
class Node
{
public:
T data;
Node* next;
Node* prev;
};
void addElement(Node& value);
private:
Node* head;
};
// Here I am making an array of Lists
template <class T>
class ListArray
{
public:
// Here is my question.
void add(Node& value); // How to give "Node" class type here ?
private:
List<T> _listArr[10];
};
// Is the below the right way to define ListArray::add, especially the way in which Node type can be passed to it ?
template <class T>
void ListArray<T>::add(List<T>::Node& value)
{
// Make a call to List::addElement and pass Node& value
_listArr[0].addElement(value);
//....
}
Could you kindly let me know how the above can be achieved ? Thanks.
Node is a nested type of a class template:
template <class T>
class ListArray
{
public:
typedef typename List<T>::Node Node_type;
void add(Node_type& value); // Refer to it as Node_type
private:
List<T> _listArr[10];
};
And:
template <class T>
void ListArray<T>::add(typename ListArray<T>::Node_type& value)
{
_listArr[0].addElement(value);
//....
}
I used typedef to define local name for node type. It is very useful - now, clients of ListArray can write code, that uses Node_type explicitly (without knowing what it actually is). This technique is used heavily in std library - usually, std:: types have tons of typedefs to allow writing flexible code.
Also, note the typename keyword - it is required in case of nested types of class templates. It indicates, that given name is the name of a type (without it, you should get a compiler error).
I have such class
template<typename T>
class ConnectionStatus:
{
public:
virtual void setStatus(const T& status) = 0;
virtual T getStatus() = 0;
};
And i want to have a reference to this class in another class, so i do this: ConnectionStatus<typename T>& status; but compiler said error: template argument 1 is invalid. So how i can make a refernce to template virtual class?
Thank you for any help.
There are two main possibilities: when you know what that template argument should be for your class and when you don't.
For the former, it's a simple case of providing it (say it's int in this case):
struct MyClass
{
ConnectionStatus<int> &m_connection_status;
};
If you don't know the argument, make your class a template class:
template <typename ConnectionStatusType>
struct MyClass
{
ConnectionStatus<ConnectionStatusType> &m_connection_status;
};
I am trying to create a class Info<P,S> which holds a pointer to another object of type Info<S,P>. I have the following code.
template <class P, class S>
class Info {
….
public:
Info(…, Info<S,P>* parentInfo) : …, parentInfo(parentInfo)
{}
…
private:
Info<S, P> *parentInfo;
};
….
typedef Info<ActualP, ActualS> OneInfo;
typedef Info<ActualS, ActualP> OtherInfo;
…
OtherInfo* parentInfo =…;
OneInfo info(…, parentInfo);
This is not compiling and saying the constructor is not a valid one (at the call).
I suppose this would cause an infinite recursion while trying to resolve. Am I right? What are the alternatives to implement this intent of referencing Info<S,P> from Info<P,S>?
Use typename to refer a type that depends of a template parameter:
template <class T>
class Info
{
public:
Info() : parentInfo(NULL) {}
Info(Info<typename T> *info) :
parentInfo(info)
{
}
private:
Info<typename T> *parentInfo;
};
int _tmain(int, _TCHAR**)
{
Info<int> parent;
Info<int> child(&parent);
}