|
Prev: Discussion: What is the best way to count all set bits in a LARGEunsigned char array(no memory limit)?
Next: Beginner Question
From: Jonathan Campbell on 30 Dec 2007 07:17 It looks like I've stumbled over some misunderstanding of templates. When I compile the code below (g++ (GCC) 4.1.2 20070502 (Red Hat 4.1.2-12) ), the first set of errors I get are: ListT5.cpp: In function �std::string toString(const std::list<T, std::allocator<_CharT> >&)�: ListT5.cpp:18: error: expected `;' before �it� ListT5.cpp:19: error: �it� was not declared in this scope ListT5.cpp: In function �std::string toString(const std::list<T, std::allocator<_CharT> >&) [with T = float]�: ListT5.cpp:30: instantiated from here ListT5.cpp:18: error: dependent-name �std::list<T,std::allocator<_CharT> >::iterator� is parsed as a non-type, but instantiation yields a type ListT5.cpp:18: note: say �typename std::list<T,std::allocator<_CharT> >::iterator� if a type is meant I do not understand the latter suggestion. Any suggestions? TIA, Jon C. -------------------------------------- #include <list> #include <string> #include <iostream> #include <sstream> #include <algorithm> #include <iterator> using namespace std; template <class T> string toString(const list<T>& l){ ostringstream os; os<< "[ "; list<T>::iterator it; // line 18 for(it = l.begin(); it!= l.end(); ++it){ os<< *it<< ' '; } os<< " ]"<< endl; return os.str(); } int main(){ list<float> x; x.push_front(4.4); x.push_front(3.3); x.push_front(2.2); x.push_front(1.1); cout<< "x = "<< toString(x)<< endl; // below works when all 'toString' stuff commented out list<float>::iterator it; cout<< "[ "; for(it = x.begin(); it!= x.end(); ++it){ cout<< *it<< ' '; } cout<< " ]"<< endl; ----------------------------------------------------------------
From: Ben Cottrell on 30 Dec 2007 07:30 Jonathan Campbell wrote: > It looks like I've stumbled over some misunderstanding of templates. > When I compile the code below (g++ (GCC) 4.1.2 20070502 (Red Hat > 4.1.2-12) ), the first set of errors I get are: > > ListT5.cpp: In function �std::string toString(const std::list<T, > std::allocator<_CharT> >&)�: > ListT5.cpp:18: error: expected `;' before �it� > ListT5.cpp:19: error: �it� was not declared in this scope > ListT5.cpp: In function �std::string toString(const std::list<T, > std::allocator<_CharT> >&) [with T = float]�: > ListT5.cpp:30: instantiated from here > ListT5.cpp:18: error: dependent-name �std::list<T,std::allocator<_CharT> > >::iterator� is parsed as a non-type, but instantiation yields a type > ListT5.cpp:18: note: say �typename std::list<T,std::allocator<_CharT> > >::iterator� if a type is meant > > I do not understand the latter suggestion. > > Any suggestions? > > TIA, > > Jon C. > > -------------------------------------- > #include <list> > #include <string> > #include <iostream> > #include <sstream> > #include <algorithm> > #include <iterator> > > using namespace std; > > template <class T> string toString(const list<T>& l){ > ostringstream os; > os<< "[ "; > list<T>::iterator it; // line 18 typename list<T>::iterator it; If I'm not mistaken, the compiler is unable to implicitly determine whether or not list<T>::iterator is a type, since list<T> is an incomplete type at this stage. the typename keyword drops the compiler a hint that list<T>::iterator is actually a type, and not something else.
From: Jonathan Campbell on 30 Dec 2007 08:21 Ben Cottrell wrote: > Jonathan Campbell wrote: >> It looks like I've stumbled over some misunderstanding of templates. [...] >> >> template <class T> string toString(const list<T>& l){ >> ostringstream os; >> os<< "[ "; >> list<T>::iterator it; // line 18 > > typename list<T>::iterator it; > > If I'm not mistaken, the compiler is unable to implicitly determine > whether or not list<T>::iterator is a type, since list<T> is an > incomplete type at this stage. the typename keyword drops the > compiler a hint that list<T>::iterator is actually a type, and not > something else. Thanks. I changed the declaration of 'it'; after that did not compile, I removed the 'const' from the argument, and then it did compile -- and execute as expected. template <class T> string toString(list<T>& l){ ostringstream os; os<< "[ "; typename list<T>::iterator it; //list<T>::iterator it; // line 18 for(it = l.begin(); it!= l.end(); ++it){ os<< *it<< ' '; } os<< " ]"<< endl; return os.str(); } I am grateful, but I wish I could claim to be generally much the wiser. I've not used a type 'variable' outside a class or function declaration before, so I'm scratching my head a bit. My question arose from the end of a series of 'back off to something simpler' experiments that I've been doing to solve a problem in an Iterator class for a List class that I'm adapting. I'll go off now and see if I can apply this to the original problem. Many thanks, Jon C.
From: Ulrich Eckhardt on 30 Dec 2007 10:27 Jonathan Campbell wrote: > It looks like I've stumbled over some misunderstanding of templates. > When I compile the code below (g++ (GCC) 4.1.2 20070502 (Red Hat > 4.1.2-12) ), the first set of errors I get are: > > ListT5.cpp: In function 'std::string toString(const std::list<T, > std::allocator<_CharT> >&)': > ListT5.cpp:18: error: expected `;' before 'it' > ListT5.cpp:19: error: 'it' was not declared in this scope > ListT5.cpp: In function 'std::string toString(const std::list<T, > std::allocator<_CharT> >&) [with T = float]': > ListT5.cpp:30: instantiated from here This is the important part: > dependent-name 'std::list<...>::iterator' is parsed as a non-type, > but instantiation yields a type This directly refers to your use of 'list<T>::iterator' in your code, which the compiler parses as a non-type but which eventually is a type instead. This is just a rule of the C++ language that it is supposed to assume a non-type there, but your instantiation resolves to a type instead. In non-template functions, the compiler can actually figure out that it is a type because all specialisations must be known at the time of use. > note: say 'typename std::list<...>::iterator' if a type is meant. > > I do not understand the latter suggestion. Well, it simply says that you should use 'typename list<T>::iterator' instead of 'list<T>::iterator'. > template <class T> string toString(const list<T>& l){ > ostringstream os; > os<< "[ "; > list<T>::iterator it; // line 18 > for(it = l.begin(); it!= l.end(); ++it){ > os<< *it<< ' '; > } > os<< " ]"<< endl; > return os.str(); > } Uli
From: Jonathan Campbell on 30 Dec 2007 12:08
Jonathan Campbell wrote: > It looks like I've stumbled over some misunderstanding of templates. Thanks guys, that's moved me forward quite a bit. I'm going to push my luck with another question. In the List class below, I have used std::list as the implementation --- just an experiment, I have a more difficult class that I want to clean up and implement as a wrapper to std::list. (Incidentally, this interface is from my own template List class which appears to work perfectly fine.) When I compile a program that #includes ListStd.h, I get the following errors, ListStd.h: In function �std::ostream& operator<<(std::ostream&, const List<T>&)�: ListStd.h:87: error: expected primary-expression before �template� ListStd.h:87: error: expected `;' before �template� ListStd.h:89: error: �it� was not declared in this scope TIA again, Jon C. ----------------------------------------------------------- // ListStd.h #ifndef LISTTH #define LISTTH #include <cassert> #include <iostream> #include <list> #include <iterator> template <class T> class List; template <class T> std::ostream& operator<<(std::ostream& os, const List<T>& l); template <class T> class List{ friend std::ostream& operator<< <T>(std::ostream& os, const List<T>& l); public: List(); List(const List<T> & other); ~List(); List & operator = (const List<T> & rhs); T front() const; void push_front(T e); void pop_front(); void clear(); bool empty() const; int size() const; private: std::list<T> l_; }; //------------------------------------------------------------- /* guessing we do not need any of these template <class T>List<T>::List(){} template <class T>List<T>::List(const List<T> & source){ l_ = source.l_; } template <class T> List<T> & List<T>:: operator = (const List<T> & source){ l_ = source.l_; return *this; } template <class T>List<T>::~List(){ l_.clear(); } */ template <class T> void List<T>::push_front(T e){ l_.push_front(e); } template <class T> T List<T>::front() const{ return l_.front(); } template <class T> void List<T>::pop_front(){ l_.pop_front(); } template <class T> void List<T>::clear(){ l_.clear(); } template <class T>bool List<T>::empty() const{ return l_.empty(); } template <class T>int List<T>::size() const{ return l_.size(); } template <class T> std::ostream& operator<< (std::ostream& os, const List<T>& l){ //std::list<T>iterator it; // line 86 template std::list<T>iterator it; // line 87 os<<"f[ "; for(it = l.l_.begin(); it!= l.l_.end(); ++it){ os<< *it<< ' '; } os<<" ]b"<<std::endl; return os; } #endif |