[Bug c++/19188] New: friend funtion inside a template class seems to have a problem
A template class(tstack class) has a singly-linked list "struct" declaration in private section. Another template class(tstackIterator) - iterator class is declared and defined in global space. If the iterator template class trys to get access to the linked list structure inside the previous class with a friend statement declared in the previous class, it does not work. It behaves in much the same way as without friend declaration. The following code shows this: //: TSTACK.H -- Stack using templates #ifndef TSTACK_H_ #define TSTACK_H_ // Some implementations require this: template class tstackIterator; template class tstack { struct link { T* data; link* next; link(T* Data, link* Next){ data = Data; next = Next; } } * head; int owns; public: tstack(int Owns = 1) : head(0), owns(Owns) {} ~tstack(); void push(T* Data) { head = new link(Data,head); } T* peek() const { return head->data; } T* pop(); int Owns() const { return owns; } void Owns(int newownership) { owns = newownership; } friend class tstackIterator; }; template T* tstack::pop() { if(head == 0) return 0; T* result = head->data; link* oldHead = head; head = head->next; delete oldHead; return result; } template tstack::~tstack() { link* cursor = head; while(head) { cursor = cursor->next; // Conditional cleanup of data: if(owns) delete head->data; delete head; head = cursor; } } template class tstackIterator { tstack::link* p; // this is line 68 // when it is compiled, g++ 3.4.1 give some error message but it does not make //sense in terms of languae. but the version g++ (GCC) 3.2.3 20030502 works fine // except that it gives a warning saying "tstack.h:68: warning: `typename //tstack::link' is implicitly a typename" //The Error message is attached to the bottom /// public: tstackIterator(const tstack& tl) : p(tl.head) {} tstackIterator(const tstackIterator& tl) : p(tl.p) {} // operator++ returns boolean indicating end: int operator++() { if(p->next) p = p->next; else p = 0; // Indicates end of list return int(p); } int operator++(int) { return operator++(); } // Smart pointer: T* operator->() const { if(!p) return 0; return p->data; } T* current() const { if(!p) return 0; return p->data; } // int conversion for conditional test: operator int() const { return p ? 1 : 0; } }; #endif // TSTACK_H_ the compiler complaints are as follows: In file included from tstktst.cpp:2: ../14/tstack.h:68: error: expected `;' before '*' token ../14/tstack.h: In constructor `tstackIterator::tstackIterator(const tstack&)': ../14/tstack.h:71: error: class `tstackIterator' does not have any field named `p' ../14/tstack.h: In copy constructor `tstackIterator::tstackIterator(const tstackIterator&)': ../14/tstack.h:73: error: class `tstackIterator' does not have any field named `p' ../14/tstack.h: In member function `int tstackIterator::operator++()': ../14/tstack.h:76: error: `p' undeclared (first use this function) ../14/tstack.h:76: error: (Each undeclared identifier is reported only once for each function it appears in.) ../14/tstack.h: In member function `T* tstackIterator::operator->() const': ../14/tstack.h:84: error: `p' undeclared (first use this function) ../14/tstack.h: In member function `T* tstackIterator::current() const': ../14/tstack.h:88: error: `p' undeclared (first use this function) ../14/tstack.h: In member function `tstackIterator::operator int() const': ../14/tstack.h:92: error: `p' undeclared (first use this function) -- Summary: friend funtion inside a template class seems to have a problem Product: gcc Version: 3.4.1 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: max656 at hotmail dot com CC: gcc-bugs at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19188
[Bug c++/19188] friend funtion inside a template class seems to have a problem
--- Additional Comments From max656 at hotmail dot com 2004-12-30 07:41 --- Thanks for the reply. In this one line of code tstack::link* p; "tstack::link " is a typename. so I can not give another name. Actually, I got other ways to get around this problem. But I am interested in this style as well. The code I am experimenting came from Bruce Eckel's old book. The 2nd edtion uses a different way from this. Anyway the definition of "tstack::link" is not created inside the class. it is used only to declare a private pointer variable named "head".Actually it is NOT defined. I think that's why g++ (GCC) 3.2.3 20030502 give the warning of "implicite typename". But a new version, g++ 3.4.1, checks it out and send out a error message of "../14/tstack.h:68: error: expected `;' before '*' token". I don't have any idea of what this means. It does not make any sense at all. Would you take a look at it and reply to me ? I really appreciate it in advance. Tyson -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19188
[Bug c++/19188] friend funtion inside a template class seems to have a problem
--- Additional Comments From max656 at hotmail dot com 2005-01-01 01:37 --- Subject: RE: friend funtion inside a template class seems to have a probl Hi lerdsuwa You came up with an interesting topic - class template specializtion. I didn't know aboou it. I need further research on that. As you mentioned, the keyword "typename' is added and compiled and then it works fine. Thanks a lot for your detailed explanation. It haunted me a lot. I was completely stuck for a while even though I found some other ways. Tyson >From: "lerdsuwa at gcc dot gnu dot org" <[EMAIL PROTECTED]> >Reply-To: [EMAIL PROTECTED] >To: [EMAIL PROTECTED] >Subject: [Bug c++/19188] friend funtion inside a template class seems to >have a problem >Date: 31 Dec 2004 13:23:03 - > >--- Additional Comments From lerdsuwa at gcc dot gnu dot org >2004-12-31 13:23 --- >The 'typename' keyword is required because later C++ introduces a lot more >features. Those that interfere with your code are partial specialization >and specialization. For example, you can now have specialization > > template <> class tstack { > int link; > ... > }; > >Then when you declare > > tstack t; > >it will use the above declaration, where 'link' is now a member data >instead of a nested class. So the code > > tstack::link* p; > >which could be interpreted as declaring a variable which is a pointer to >type >'tstack::link' if 'T' is 'int'. But when 'T' is 'bool' it could means >multiplying a member data with another variable named 'p'. > >To resolve the ambiguity, later C++ requires the 'typename' keyword to >treat as pointer declaration, otherwise it will be treated as >muliplication. >Older C++ books don't have this 'typename' keyword but newer good books >from respected authors coming out in the last few years should. >(Many new C++ books are still wrong). > >I know the parser error message could be improved, and there are plenty of >bug reports elsewhere about it. > >-- > > >http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19188 > >--- You are receiving this mail because: --- >You reported the bug, or are watching the reporter. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19188