DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 9 of 9

Thread: Template declaration issue with the scope

  1. #1
    Join Date
    Nov 2005
    Posts
    22

    Question Template declaration issue with the scope

    Hi,

    I have a code which gets compiled using gcc 2.3. However I am getting some errors with gcc 3.4.6.

    Here is the code snippet:

    Code:
    NAMESPACE_BEGIN(utils)
    
    //
    // template class list
    //
    template <class _Ty>
    class list
    {
    protected:
        //
        // struct Node & Nodeptr
        // - Each element in the list is a struct Node
        //
        struct Node;
        friend struct Node;
        typedef Node *Nodeptr;
    
    public:
        //
        // This is what is being defined (the type of 'this')
        //
        typedef list<_Ty> _Myt;
    
        //
        // Forward & friend declarations for the iterators
        //
        class iterator;
        friend class iterator;
        class const_iterator;
        friend class const_iterator;
    
            //
        // iterator()
        //
        class iterator
        {
        public:
            // Constructors
            iterator()
            {
            }
    
            iterator(Nodeptr __P)
                : _Ptr(__P)
            {
            }
    
            _Ty &operator *() const
            {
                return Acc::Value(_Ptr);
            }
    
            // Prefix ++
            iterator& operator ++()
            {
                _Ptr = Acc::Next(_Ptr);
                return (*this);
            }
    
            // Postfix ++
            iterator operator ++(int)
            {
                iterator _Tmp = *this;
                ++*this;
                return (_Tmp);
            }
    
            // Prefix --
            iterator& operator --()
            {
                _Ptr = Acc::Prev(_Ptr);
                return (*this);
            }
    
            // Postfix --
            iterator operator --(int)
            {
                iterator _Tmp = *this;
                --*this;
                return (_Tmp);
            }
    
            bool operator ==(const iterator& __X) const
            {
                return (_Ptr == __X._Ptr);
            }
    
            bool operator !=(const iterator& __X) const
            {
                return (!(*this == __X));
            }
    
            Nodeptr Mynode() const
            {
                return (_Ptr);
            }
    
        protected:
            Nodeptr        _Ptr;
        }; // end iterator
    
        //
        // const_iterator
        //
        class const_iterator : public iterator
        {
        public:
            // Constructors
            const_iterator()
            {
            }
            const_iterator(Nodeptr __P)
                : iterator(__P)
            {
            }
            const_iterator(const iterator& __X)
                : iterator(__X)
            {
            }
    
            const _Ty& operator *() const
            {
                return (Acc::Value(_Ptr)); //error: line 148 `_Ptr' was not declared in this scope
            }
    
            // Prefix ++
            const_iterator& operator ++()
            {
                _Ptr = Acc::Next(_Ptr); //error: line 154 `_Ptr' was not declared in this scope
                return (*this);
            }
    
            // Postfix ++
            const_iterator operator ++(int)
            {
                iterator _Tmp = *this;
                ++*this;
                return (_Tmp);
            }
    
            // Prefix --
            const_iterator& operator --()
            {
                _Ptr = Acc::Prev(_Ptr); //error: line 169 `_Ptr' was not declared in this scope
                return (*this);
            }
    
            // Postfix --
            const_iterator operator --(int)
            {
                iterator _Tmp = *this;
                --*this;
                return (_Tmp);
            }
    
            bool operator ==(const const_iterator& __X) const
            {
                return (_Ptr == __X._Ptr); //error: line 183 `_Ptr' was not declared in this scope
            }
    
            bool operator !=(const const_iterator& __X) const
            {
                return (!(*this == __X));
            }
        }; // end const_iterator
    I get below errors with gcc 3.4.6:

    ../include/list.h:148: error: `_Ptr' was not declared in this scope
    ../include/list.h: In member function `utils::list<_Ty>::const_iterator& utils::list<_Ty>::const_iterator::operator++()':
    ../include/list.h:154: error: `_Ptr' was not declared in this scope
    ../include/list.h: In member function `utils::list<_Ty>::const_iterator& utils::list<_Ty>::const_iterator::operator--()':
    ../include/list.h:169: error: `_Ptr' was not declared in this scope
    ../include/list.h: In member function `bool utils::list<_Ty>::const_iterator::operator==(const utils::list<_Ty>::const_iterator&) const':
    ../include/list.h:183: error: `_Ptr' was not declared in this scope

    It will be highly appreciated if someone can please shed some light on this?

  2. #2
    Join Date
    Oct 2007
    Posts
    369
    You've left some stuff out. for one thing, You didn't show the end of your list class or namespace. const_iterator doesn't have any members.

    What is "Acc", used in your iterator classes?

    You might want to consider *not* using the same name for the class member variable (_Ptr) in all classes.

  3. #3
    Join Date
    Nov 2003
    Posts
    4,118
    You need to #include a complete declaration of struct node, not just a forward declaration thereof.
    Danny Kalev

  4. #4
    Join Date
    Nov 2005
    Posts
    22
    Here is the complete list.h file:
    Code:
    // list standard header
    #ifndef __UTILS_LIST__
    #define __UTILS_LIST__
    
    NAMESPACE_BEGIN(utils)
    
    //
    // template class list
    //
    template <class _Ty>
    class list
    {
    protected:
        //
        // struct Node & Nodeptr
        // - Each element in the list is a struct Node
        //
        struct Node;
        friend struct Node;
        typedef Node *Nodeptr;
    
    public:
        //
        // This is what is being defined (the type of 'this')
        //
        typedef list<_Ty> _Myt;
    
        //
        // Forward & friend declarations for the iterators
        //
        class iterator;
        friend class iterator;
        class const_iterator;
        friend class const_iterator;
    
            //
        // iterator()
        //
        class iterator
        {
        public:
            // Constructors
            iterator()
            {
            }
    
            iterator(Nodeptr __P)
                : _Ptr(__P)
            {
            }
    
            _Ty &operator *() const
            {
                return Acc::Value(_Ptr);
            }
    
            // Prefix ++
            iterator& operator ++()
            {
                _Ptr = Acc::Next(_Ptr);
                return (*this);
            }
    
            // Postfix ++
            iterator operator ++(int)
            {
                iterator _Tmp = *this;
                ++*this;
                return (_Tmp);
            }
    
            // Prefix --
            iterator& operator --()
            {
                _Ptr = Acc::Prev(_Ptr);
                return (*this);
            }
    
            // Postfix --
            iterator operator --(int)
            {
                iterator _Tmp = *this;
                --*this;
                return (_Tmp);
            }
    
            bool operator ==(const iterator& __X) const
            {
                return (_Ptr == __X._Ptr);
            }
    
            bool operator !=(const iterator& __X) const
            {
                return (!(*this == __X));
            }
    
            Nodeptr Mynode() const
            {
                return (_Ptr);
            }
    
        protected:
            Nodeptr        _Ptr;
        }; // end iterator
    
        //
        // const_iterator
        //
        class const_iterator : public iterator
        {
        public:
            // Constructors
            const_iterator()
            {
            }
            const_iterator(Nodeptr __P)
                : iterator(__P)
            {
            }
            const_iterator(const iterator& __X)
                : iterator(__X)
            {
            }
    
            const _Ty& operator *() const
            {
                return (Acc::Value(_Ptr));
            }
    
            // Prefix ++
            const_iterator& operator ++()
            {
                _Ptr = Acc::Next(_Ptr);
                return (*this);
            }
    
            // Postfix ++
            const_iterator operator ++(int)
            {
                iterator _Tmp = *this;
                ++*this;
                return (_Tmp);
            }
    
            // Prefix --
            const_iterator& operator --()
            {
                _Ptr = Acc::Prev(_Ptr);
                return (*this);
            }
    
            // Postfix --
            const_iterator operator --(int)
            {
                iterator _Tmp = *this;
                --*this;
                return (_Tmp);
            }
    
            bool operator ==(const const_iterator& __X) const
            {
                return (_Ptr == __X._Ptr);
            }
    
            bool operator !=(const const_iterator& __X) const
            {
                return (!(*this == __X));
            }
        }; // end const_iterator
    
        //
        // list<> constructors()
        //
        explicit list()
            : _Head(Buynode()), _Size(0)
        {
        }
        explicit list(size_t __N, const _Ty& _V = _Ty())
            : _Head(Buynode()), _Size(0)
        {
            insert(begin(), __N, _V);
        }
        list(const _Myt& __X)
            : _Head(Buynode()), _Size(0)
        {
            insert(begin(), __X.begin(), __X.end());
        }
    
        // Destructor
        ~list()
        {
            erase(begin(), end());
            Freenode(_Head);
            _Head = 0, _Size = 0;
        }
    
        _Myt& operator =(const _Myt& __X)
        {
            if (this != &__X)
            {
                iterator _F1 = begin();
                iterator _L1 = end();
                const_iterator _F2 = __X.begin();
                const_iterator _L2 = __X.end();
                for (; _F1 != _L1 && _F2 != _L2; ++_F1, ++_F2)
                    *_F1 = *_F2;
                erase(_F1, _L1);
                insert(_L1, _F2, _L2);
            }
            return (*this);
        }
    
        //
        // Return const and non-const iterators
        //
        iterator begin()
        {
            return (iterator(Acc::Next(_Head)));
        }
        const_iterator begin() const
        {
            return (const_iterator(Acc::Next(_Head)));
        }
        iterator end()
        {
            return (iterator(_Head));
        }
        const_iterator end() const
        {
            return (const_iterator(_Head));
        }
    
        size_t size() const
        {
            return (_Size);
        }
    
        bool empty() const
        {
            return (size() == 0);
        }
    
        _Ty front()
        {
            return (*begin());
        }
    
        const _Ty front() const
        {
            return (*begin());
        }
    
        _Ty back()
        {
            return (*(--end()));
        }
    
        const _Ty back() const
        {
            return (*(--end()));
        }
    
        iterator push_front(const _Ty& __X)
        {
            return insert(begin(), __X);
        }
    
        // pop_front now returns the 'popped' element
        _Ty pop_front()
        {
            _Ty t = *begin();
            erase(begin());
            return t;
        }
    
        iterator push_back(const _Ty& __X)
        {
            return insert(end(), __X);
        }
    
        // pop_back now returns the 'popped' element
        _Ty pop_back()
        {
            _Ty t = *--end();
            erase(end());
            return t;
        }
    
        void assign(const_iterator __F, const_iterator __L)
        {
            erase(begin(), end());
            insert(begin(), __F, __L);
        }
    
        void assign(size_t __N, const _Ty& __X = _Ty())
        {
            erase(begin(), end());
            insert(begin(), __N, __X);
        }
    
        iterator insert(iterator __P, const _Ty& __X = _Ty())
        {
            Nodeptr __S = __P.Mynode();
            Nodeptr _tmp = Buynode(__S, Acc::Prev(__S));
            if (_tmp)
            {
                Acc::Prev(__S) = _tmp;
                __S = Acc::Prev(__S);
                Acc::Next(Acc::Prev(__S)) = __S;
                Acc::Value(__S) = __X;
                ++_Size;
    
                return (iterator(__S));
            }
            return (iterator(0));
        }
    
        void insert(iterator __P, size_t __M, const _Ty& __X)
        {
            for (; 0 < __M; --__M)
                insert(__P, __X);
        }
    
        void insert(iterator __P, const _Ty *__F, const _Ty *__L)
        {
            for (; __F != __L; ++__F)
                insert(__P, *__F);
        }
    
        void insert(iterator __P, const_iterator __F, const_iterator __L)
        {
            for (; __F != __L; ++__F)
                insert(__P, *__F);
        }
    
        iterator erase(iterator __P)
        {
            Nodeptr __S = (__P++).Mynode();
    
            Acc::Next(Acc::Prev(__S)) = Acc::Next(__S);
            Acc::Prev(Acc::Next(__S)) = Acc::Prev(__S);
    
            Freenode(__S);
            --_Size;
    
            return (__P);
        }
    
        iterator erase(iterator __F, iterator __L)
        {
            while (__F != __L)
                erase(__F++);
            return (__F);
        }
    
        void clear()
        {
            erase(begin(), end());
        }
    
        void remove(const _Ty& _V)
        {
            iterator __L = end();
            for (iterator __F = begin(); __F != __L; )
                if (*__F == _V)
                    erase(__F++);
                else
                    ++__F;
        }
    
        void replace(const _Ty &Old, const _Ty &New)
        {
            iterator        __L = end();
    
            for (iterator __F = begin(); __F != __L; )
                if (*__F == Old)
                {
                    *__F++ = New;
                }
                else
                    ++__F;
        }
    
    
    
    
    protected:
    
        struct Node
        {
            struct Node    *_Next;
            struct Node    *_Prev;
            _Ty             _Value;
        };
    
        //
        // struct Acc
        // - This is used to access the members of the Node struct above.
        // - XXX: Why is a separate struct needed?
        //
        struct Acc;
        friend struct Acc;
        struct Acc
        {
            typedef Nodeptr &Nodepref;
    
            // Next()
            static Nodepref Next(Nodeptr __P)
            {
                return ((Nodepref)(*__P)._Next);
            }
    
            // Prev()
            static Nodepref Prev(Nodeptr __P)
            {
                return ((Nodepref)(*__P)._Prev);
            }
    
            // Value()
            static _Ty& Value(Nodeptr __P)
            {
                return ((_Ty&)(*__P)._Value);
            }
        };
    
        // Allocate a new node
        Nodeptr Buynode(Nodeptr Narg = 0, Nodeptr Parg = 0)
        {
            Nodeptr S = (Nodeptr) calloc(1, sizeof (Node));
            if (S)
            {
                Acc::Next(S) = Narg != 0 ? Narg : S;
                Acc::Prev(S) = Parg != 0 ? Parg : S;
            }
            return (S);
        }
    
        void Freenode(Nodeptr S)
        {
            free(S);
        }
    
    
        //
        // List data:
        //
        Nodeptr    _Head;
        size_t     _Size;
    
    }; // end class list
    
    NAMESPACE_END
    
    #endif /* __UTILS_LIST__ */
    Hope this helps someone finding the solution of the errors that I am getting. Please help.

  5. #5
    Join Date
    Nov 2005
    Posts
    22
    Code:
            const _Ty& operator *() const
            {
                return (Acc::Value(iterator::_Ptr));
            }
    Doing above change solved the issue.

  6. #6
    Join Date
    Oct 2007
    Posts
    369
    Using g++ 3.4.4, I was able to implement a similar "fix". There seems to be a problem with g++. I've seen this before: when templates are involved (the only pattern I've seen), the compiler sometimes has trouble "seeing" an exposed member of a base class.

  7. #7
    Join Date
    Dec 2007
    Posts
    401

  8. #8
    Join Date
    Oct 2007
    Posts
    369
    Wow. That *does* hurt my head. Is their statement true that it is not valid C++?
    Code:
    // from http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19
     template<typename T>
     class B {
     public:
       void f() { }  // member of class B<T>
     };
     
     template<typename T>
     class D : public B<T> {
     public:
       void g()
       {
         f();  // bad (even though some compilers erroneously (temporarily?) accept it)
       }
     };

  9. #9
    Join Date
    Dec 2007
    Posts
    401
    > Is their statement true that it is not valid C++?

    Yes.

    From the GNU documentation for g++ at http://gcc.gnu.org/onlinedocs/gcc/Na...ml#Name-lookup
    The C++ standard prescribes that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class. Only names that are dependent are looked up at the point of instantiation.
    ...
    This distinction between lookup of dependent and non-dependent names is called two-stage (or dependent) name lookup. G++ implements it since version 3.4.
    ...
    Note that some compilers (including G++ versions prior to 3.4) get these examples wrong and accept above code without an error. Those compilers do not implement two-stage name lookup correctly.

Similar Threads

  1. Excel question
    By garywillams in forum C++
    Replies: 1
    Last Post: 09-11-2009, 09:56 AM
  2. template management of the website
    By anitha2324 in forum AJAX
    Replies: 0
    Last Post: 06-18-2008, 04:22 AM
  3. SQL Insert Trigger; variable scope issue
    By rkbnair in forum Database
    Replies: 1
    Last Post: 05-31-2006, 03:52 AM
  4. VB/ADO Scope issue with Recordset
    By mjulson in forum VB Classic
    Replies: 1
    Last Post: 06-05-2002, 12:27 PM
  5. Scope issue in a UDF/SP
    By Stephen Russell in forum Database
    Replies: 0
    Last Post: 04-24-2002, 07:47 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center