i try to design a template for my university project. i wrote the follwing code:
#ifndef _LinkedList_H_
#define _LinkedList_H_
#include "Link.h"
#include <ostream>
template <class L>//error one
class LinkedList
{
private:
Link<L> *pm_head;
Link<L> * pm_tail;
int m_numOfElements;
Link<L>* FindLink(L * dataToFind);
public:
LinkedList();
~LinkedList();
int GetNumOfElements(){return m_numOfElements;}
bool Add( L * data);
L *FindData(L * data);
template <class L> friend ostream & operator<<(ostream& os,const LinkedList<L> listToprint);//error two
L* GetDataOnTop();
bool RemoveFromHead();
L* Remove(L * toRemove);
this templete uses the link class templete
#ifndef _Link_H_
#define _Link_H_
template <class T>//error 3
class Link
{
private:
T* m_data;
Link* m_next;
Link* m_prev;
public:
Link(T* data);
~Link(void);
bool Link::operator ==(const Link& other)const;
/*getters*/
Link* GetNext()const {return m_next;}
Link* GetPrev()const {return m_prev;}
T* GetData()const {return m_data;}
//setters
void SetNext(Link* next) {m_next = next;}
void SetPrev(Link* prev) {m_prev = prev;}
void SetData(T* data) {m_data = data;}
};
error one: shadows template parm `class L'
error two:declaration of `class L'
error three: shadows template parm `class T'
i dont understand what is the problem. i can really use your help
thank you :)
These error messages really belong together:
a.cc:41: error: declaration of ‘class L’
a.cc:26: error: shadows template parm ‘class L’
This means that in line 41, you introduce a template parameter L; in my copy, this refers to
template <class L> friend ostream & operator<<(ostream& os,
const LinkedList<L> listToprint);//error two
And that declaration shadows the template parameter in line 26:
template <class L>//error one
class LinkedList
You need to rename the template parameter in the friend declaration.
Edit: The relevant language specification is 14.6.1/7
A template-parameter shall not be
redeclared within its scope (including
nested scopes). A template-parameter
shall not have the same name as the
template name.
When you refer to L in const LinkedList<L> listToprint, it's not clear whether you mean the L of the friend or the L of the class. So write
template <class L1> friend ostream & operator<<(ostream& os,
const LinkedList<L1> listToprint);
Just remove the
template <class L>
from the friend member function declaration.
You also need to replace uses of ostream with std::ostream unless you have a using namespace std somewhere in your code.
Otherwise, the code looks fine.
Related
I am having trouble with defining an operator that is within a nested class that is also templated. I understand how to declare and define it within the .h file, but I want to declare it in the .h file and define it in a .hpp file. For example:
List.h
template <typename T>
class List {
public:
class const_iterator { //nested class
//....
const T & operator*() const;
};
};
Now here is the part I don't quite understand:
List.hpp
#include "List.h"
template <typename T>
typename List <T>::const_iterator & List <T>:: operator*() const //error line
{
//do stuff
}
The error I am receiving on line 4 of the Line.hpp is:
Out-of-line definition of 'operator*' does not match any declaration in 'List<T>'
I am looking for a solution that involves solely fixing the .hpp file.
As the error says, your definition doesn't match your declaration. You've declared a member operator* of the class List<T>::const_iterator that returns a const T&, but your definition is for the member operator* of the class List<T> that returns a List<T>::const_iterator&.
Definitions of member functions of class templates, nested or not, follow the same pattern as any other function: ReturnType FunctionName(ParameterList)
The appropriate definition for that declaration is:
template <typename T>
const T& List<T>::const_iterator::operator*( ) const
//^^^^^^^^ ^
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
// Return type | (empty) parameter list
// Function name
{
//...
}
Your .hpp is trying to define an operator* that is a member of List<T> and returns a reference to a List<T>::const_iterator. That is not what your .h declares. It declares an operator* that is a member of List<T>::const_iterator and returns a reference to a T.
Try this instead:
#include "List.h"
template <typename T>
const T& List<T>::const_iterator::operator*() const
{
//do stuff
}
This question already has an answer here:
Nested templates with dependent scope
(1 answer)
Closed 6 years ago.
having trouble when trying to compile a template class.
In the .h file
template <typename dataType>
class Node {
private:
dataType nodeData;
Node<dataType>* nextLink;
Node<dataType>* previousLink;
public:
Node(const dataType& nodeData);
// methods
In the .template file
template <typename dataType>
Node<dataType>::dataType Node<dataType>::getData() const {
return nodeData;
};
The error I get when trying to compile is:
need ‘typename’ before ‘Node<dataType>::dataType’ because ‘Node<dataType>’ is a dependent scope
Node<dataType>::dataType Node<dataType>::getData() const {
So then I add typename and it then gives me this error:
error: expected nested-name-specifier before ‘dataType’
typename dataType getData() const;
^
error: expected ‘;’ at end of member declaration
error: declaration of ‘int Node<dataType>::dataType’
error: shadows template parm ‘class dataType’
template <typename dataType>
^
What have I done wrong?
There is no member called dataType, I assume the return type should be just the template dataType:
template <typename dataType>
dataType Node<dataType>::getData() const {
return nodeData;
}
The compiler message is misleading in this case as it doesn't find proper definition, it assumes the dataType refers to the template argument.
template <typename DataType>
class Node {
public:
using dataType = DataType;
private:
dataType nodeData;
Node<dataType>* nextLink;
Node<dataType>* previousLink;
public:
Node(const dataType& nodeData);
dataType getData() const;
};
template <typename DataType>
typename Node<DataType>::dataType Node<DataType>::getData() const {
return nodeData;
};
specfy typename like this.
http://melpon.org/wandbox/permlink/Agu2s6vw6OLfbbRh
The presented example code is incomplete, so one would have to guess at the concrete problem.
However, here's how to do that class in a practical way, without problems like the one you're encountering:
template< class Item >
struct Node
{
Node* next;
Node* prev;
Item item;
};
Showing that it's sometimes possible to solve a problem without knowing the exact details.
everyone
I am a beginner of c++. Now I try to understand how compiler lookup a function with friend keyword.
The followings are the code with warning and error messages.
I have two problems in the code. One is warning and another is error.
At Problem(1), compiler warns that function including template parameter is non-template function. Why is it non-template function? And how can I define a function including template parameter as non-template function?
At Problem(2), friend template function, friendFunction(A const& val), is not looked up. In my understanding, it can be looked up by ADL method.
Please tell me how to understand the two problem above.
Thank you very much.
template<typename T>
class A {
/* ***** first declaration of functions without definition.
* ***** In this case, compiler assume the friend function will be defined
* ***** in one outer namespace, in this case ::. */
friend void friendFunction(A<T> const& val); // Problem(1) warning: please see below for message
// warning: friend declaration ‘void friendFunction(const A<T>&)’ declares a non-template function
};
// ??? How can I define friend void friendFunction(A<T> const& val) ???
template<typename T>
void friendFunction(A<T> const& val) {
std::cout << "::function(A<T>)" << std::endl;
}
void call_FriendFunction(A<int>* ptr);
void test_friend_keyword() {
A<int> a;
call_FriendFunction(&a);
}
void call_FriendFunction(A<int>* ptr) {
friendFunction(*ptr); // Problem(2) please see error message below
// undefined reference to `friendFunction(A<int> const&)'
/* In my understanding, the following friendFunction(*ptr); can be looked up
* by the following logic.
* (1) friendFunction(ptr) here is unqualified name.
* (2) Because friendFunction(*ptr) has an augment of A<int>* ptr,
* friendFunction(*ptr) have related class and related namespace of class A.
* (3) class A has declaration of
* friend void friendFunction(A<T> const& val);
* And it is allowed to see the friend template function.
* (4) As a result, friendFunction(*ptr) is looked up as
* friend void ::friendFunction(A<T> const& val); */
}
For the warning with
friend void friendFunction(A<T> const& val);
Assume that T in int, it declares
friend void friendFunction(A<int> const& val);
So you have to define
void friendFunction(A<int> const& val);
which is not the same as
template<typename T>
void friendFunction(A<int> const& val);
or even
template<>
void friendFunction<int>(A<int> const& val);
The possible fixes are to declare a template function friendFunction before:
template<typename T> class A;
template <typename T> void friendFunction(A<T> const& val);
template<typename T>
class A {
friend void friendFunction<>(A<T> const& val); // It is the template function
// Only the one with T is friend.
};
Live Demo
Or to provide definition inside the class:
template<typename T>
class A {
friend void friendFunction(A<T> const& val) // It is not template
{
/*Definition*/
}
};
Demo
So I have this templated class called list
//List.h
#ifndef LIST_H
#define LIST_H
#include<fstream>
template <class T>
class List
{
private:
struct ListNode
{
T value;
ListNode* next;
ListNode* prev;
ListNode(T value1, ListNode* next1 = NULL, ListNode* prev1 = NULL)
{
value = value1;
next = next1;
prev = prev1;
}
};
ListNode* head;
ListNode* tail;
public:
List() {head = NULL; tail = NULL;};
~List();
void PrintForward(std::ostream &out);
void PrintBackward(std::ostream &out);
void InsertFront(const T &item);
void InsertRear(const T &item);
bool InsertAsNth(int N, const T &item);
bool DeleteFront(T &val);
bool DeleteRear(T &val);
bool DeleteNth(int N, T &val);
int DeleteAllOccur(const T &item);
std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
};
#endif
Now I have been trying to get this to compile but with no success. I know it has to do with the way I have the ostream operator overloaded but unfortunately I really do not know/could not find a better way.
also this is my compiler error
warning C4346: 'List<T>::ListNode' : dependent name is not a type prefix with 'typename' to indicate a type
std::ostream& operator<< (std::ostream &out, List::ListNode const* p);
has to become
std::ostream& operator<< (std::ostream &out, typename List::ListNode const* p);
or maybe even
std::ostream& operator<< (std::ostream &out, typename List<T>::ListNode const* p);
to be more explicit.
Because ::ListNode is a dependant type of the templated class List and the C++ compiler needs a little hint there. The warning is actually surprisingly helpful in this case, which cannot be said for many template related ones :)
The compiler error says exactly what is wrong and what you have to do: List<T>::Node is a qualified-id dependent on a template parameter, so the compiler cant be sure if Node is a type or a value. So you have to write typename before it to tell the compiler that Node is a type.
I suggest you to checkout this question: Where and why do I have to put the "template" and "typename" keywords?
There are at least two major problems with your code. The most
critical is that you are making operator<< a member, and
trying to give it three parameters, Which is completely illegal.
If the first parameter is to be an std::ostream&, there is no
way you can define it as a member; it must be a free function.
If it also needs access to private data, then you'll have to
make it a friend. But be aware:
friend std::ostream& operator<<( std::ostream&, typename List::ListNode const* );
makes a non-template function friend. A different non-template
function for each instantiation of the template. This is rarely
what is wanted. You can make a specific template instantiation
friend, but only if the template function is declared before
hand. Which is impossible in this case, because one of the
arguments of the function has a nested type. The more idiomatic
way of solving this (in my experience, anyway) is to define the
friend inline:
friend std::ostream& operator<<( std::ostream& dest, typename List::ListNode const& p )
{
// ...
}
In this case, operator<< is also a non-templated function, but
the definition is nested in the class template, so you will get
a new instance of the function automatically.
So I have some problems with my template class.
<!-- language: lang-c++ -->
template<class T>
class List {
class Counter
{
T real;
T imaginary;
Counter *next;
//....
public:
Counter(T a=0,T b=0);
virtual ~Counter();
friend ostream& operator<<(ostream&,Counter&);
friend ostream& operator<<(ostream&,List&);
};
Counter* first;
Counter* last;
//....
};
But I have some problems with methods. If i write function as
template<class T> Counter operator/(Counter &one,...)
When I look at Counter in VC++10 it says something like
<error_type>&one
for example. Should I use template<class T> for my Counter class everywhere in the code?
//Methods
//Counter. For example some methods
Counter operator/(Counter& one,Counter& two){}
ostream& operator<<(ostream&os,Counter&x){}
istream& operator>>(istream&is,Counter&x){}
//List
template<class T>void List<T>::add(Counter *T,int i,bool c){}
It depends on whether you define the operators (regardless of whether they are member functions or global operators) inside the class definition or outside of it.
If you do it inside the class definition, there is no need for template<T>, nor for List<T>:
template <typename T>
class List
{
public:
class Counter
{
/* This is a global operator* defined inside the class, and
as friend. */
friend Counter operator*(const Counter &c1, const Counter &c2)
{
return Counter();
}
};
};
(Note that my definition of operator* isn't actually useful because it always returns an empty Counter object. This is just to demonstrate the syntax.)
But if you define the operator outside the class (and therefore outside the template definition for List as well), you have to use the full syntax of a function template definition:
template <typename T>
typename List<T>::Counter operator/(const typename List<T>::Counter &c1, const typename List<T>::Counter &c2)
{
return List<T>::Counter();
}
As you can see, this involves three steps:
Put template <....>, with the names of all template parameters enclosed in <...> before the definition.
Use List<T>::Counter to indicate that Counter is a nested typename
Use typename List<T>::Counter because Counter is nested into a dependent type (i.e. a type that depends on a template argument).