Thread: Declare a template class as a friend?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    May 2003
    Posts
    82

    Declare a template class as a friend?

    I'm feeling really silly as this is just a syntax detail, but I have not managed to find a decent example on the web or in my textbooks.

    How do you define a template class declared outside the class as a friend? I'm working on a linked list container class, and defining my List class as a friend of Iterator, which looks something like this:

    iterator.h
    Code:
    #include "node.h"
    
    template <class T>
    class Iterator
    {
    	// declare class List as a friend somewhere?
    	public:
    		typedef *Node<T> nodePtr;
    
    		T& operator*();
    		bool operator==();
    		//etc
    	private:
    		nodePtr dataNode;
    		void setNext();
    		void setPrev();
    		void getNext();
    		// etc accessors/mutators for node manipulation
    }
    list.h
    Code:
    #include "iterator.h"
    
    template <class T>
    class List
    {
    	public:
    		typedef Iterator<T> iterator;
    
    		void push_back(const T& val);	// functions need access to Iterator's 
    		void push_front(const T& val);	// private methods to change sequence
    		void insert(iterator pos);	// of list.
    	private:
    		iterator head;
    		iterator tail;
    };
    They're may be some syntax errors. I don't have the code in front of me, so I'm just typing this in notepad from memory.

    I looked at the STL list header, and they got around this buy declaring their iterator inside the list function, but I'm not sure thats appropriate for this project. I found plenty of examples on how to declare a non-template class as a friend, and I experimented with possible ways of writing a template version, but my compiler didn't like any of them. In case it effects the template syntax, I'm currenty using MS VC++ 6.0 SP 4.

    Thank you,
    AH_Tze

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Code:
    template <class T>
    class List
    {
        friend class Iterator<T>;
    ...
    };
    gg

  3. #3
    Registered User
    Join Date
    May 2003
    Posts
    82
    Just plugged that into Dev-C++, although I switched the friend, so within Iterator class definition it declares "friend class List<T>".

    Compiles with an "List is not a template" error. After looking at non-template friend examples, I think I need some placeholder code in iterator.h which tells the compiler a class List will be defined, but I'm not sure how to write this for a template class.

    I wrote a quicky test program in which class List tries to access class Iterator's private member function. Hopefully this will illustrate my problem.

    main.cpp
    Code:
    #include "list.h"
    
    int main(int argc, char *argv[])
    {
        List<int> testList;
        int testVal;
        
        testVal = testList.getData();
      
      system("PAUSE");	
      return 0;
    }
    list.h
    Code:
    #ifndef LIST_H
    #define LIST_H
    
    #include "iterator.h"
    
    template <class T>
    class List
    {
      
        private:
            Iterator<T> data;
    
        public:
                    
            T getData() {
                    return *(data.getdata());   // access private member of data
            }
    };
    
    #endif
    iterator
    Code:
    #ifndef ITERATOR_H
    #define ITERATOR_H
    
    template <class T>
    class Iterator
    {
        //friend class List<T>; // compile error
        
        private:
            T* dataPtr;
    
            T* getdata() {
                    return dataPtr;
            }
    
            public:
            Iterator() {
                    dataPtr = NULL;
            }
    
    };
    
    #endif

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    No declaration for List is present in iterator.h, so naturally the compiler won't recognize a friend declaration. You can either include list.h in iterator.h, or create a forward declaration for list in iterator.h to bring a declaration within scope.
    My best code is written with the delete key.

  5. #5
    Registered User
    Join Date
    May 2003
    Posts
    82
    ahh... forward declaration. I think that was what I was looking for.

    In iterator.h, before the class, I added
    Code:
    template<class T>
    class List;
    And now it works like I wanted it to. The depressing thing is that I think I did that exact same thing earlier in VC++ 6.0 and it gave me an error. Or maybe it was just a typo on my part.

    Either way, thank you Prelude and Codeplug.

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >The depressing thing is that I think I did that exact same thing earlier in VC++ 6.0 and it gave me an error.
    How is that depressing? VC++ 6.0 sucks and it's not your fault.
    My best code is written with the delete key.

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Code:
    template <class T> class B; // forward decl.
    
    template <class T>
    class A
    {
        T t;
    
    public:
        void Test(const B<T> &b) {t = b.t;}
    };//A
    
    template <class T>
    class B
    {
        friend class A<T>; // friend decl.
        T t;
    };//B
    Now you have an example of a forward and friend template class declaration.

    gg

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I did the example in VC++ 6.0

    gg

  9. #9
    Registered User
    Join Date
    May 2003
    Posts
    82
    If you break it up into a driver and seperate headers for each class it no longer works.

  10. #10
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Code:
    // a.h
    template <class T> class B; // forward decl.
    
    template <class T>
    class A
    {
        T t;
    
    public:
        void Test(const B<T> &b) {t = b.t;}
    };
    
    ***************************************************
    
    // b.h
    template <class T> class A; // forward decl.
    
    template <class T>
    class B
    {
        friend class A<T>;
        T t;
    };
    
    ***************************************************
    
    // main.cpp
    #include "b.h"
    #include "a.h"
    
    int main()
    {
        A<int> a;
        B<int> b;
    
        a.Test(b);
    
        return 0;
    }//main
    Works fine.

    gg

  11. #11
    Registered User
    Join Date
    May 2003
    Posts
    82
    ah... you need two forward declarations.
    /me takes double dose of Flinstone Kids Obvious Pills (tm)

    This changes things. Danke.

    EDIT:
    wait, I spoke too soon.
    debugging....

    EDIT of the EDIT:
    d'oh, typo. had an extra set of brackets on the forward declaration. But now both your example and my actual List class are working. My fault, not VC++'s.
    Thank you again.
    Last edited by AH_Tze; 05-19-2004 at 09:31 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  2. template class default constructor problem
    By kocika73 in forum C++ Programming
    Replies: 3
    Last Post: 04-22-2006, 09:42 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Instantiating a template class
    By NullS in forum C++ Programming
    Replies: 11
    Last Post: 02-23-2005, 10:04 AM
  5. Operator overloading in template classes
    By moejams in forum C++ Programming
    Replies: 5
    Last Post: 07-21-2003, 05:16 PM