Thread: I am having trouble with friend functions

  1. #1
    Registered User
    Join Date
    Aug 2011
    Posts
    28

    I am having trouble with friend functions

    I have the following classes to implement building an expression tree. I have a function that I am having trouble placing: the buildTree function in class Tree. I am getting an undefined reference error. How can I declare it so that I may call the function in main but still access what i need to access from the classes?

    Code:
    template<class object>
    struct Node
    {
      object info;
      Node *next;
      Node<object>():info(0), next(NULL) {}
      Node<object>(const object &element, Node *n = NULL):
        info(element), next(n){}
    };
    template<class object>
    class Stack
    {
    public:
      Stack();
      ~Stack();
      void makestackempty();
      bool stackEmpty() const;
      void push(object &item);
      void pop (object &item);
      void printStack() const;
    private:
      Node<object> *top;
    };
    template<class object>
    struct TreeNode
    {
      object info;
      TreeNode *right;
      TreeNode *left;
      TreeNode()
      {}
    };
    
    template<class object>
    class Tree
    {
    private:
      TreeNode<object> *root;
    public:
      Tree();
      ~Tree();
      Tree(const Tree<object> &rhs);  // copy
      void operator=(const Tree<object> &rhs);
      void copyconst(TreeNode<object> *orig, TreeNode<object> *&rhs);
      void makeEmpty(TreeNode<object> *&tree);
      bool isEmpty()const;
      friend void buildTree(TreeNode<object> *&tree);
      void printTree(TreeNode<object> *&tree)const;
    };
    In main i currently have:
    Code:
      Tree<string> T;
      cout << "Enter postfix expression to convert:" << endl;
      buildTree(T);
    Any insight would be appreciated.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Make sure you declare the function before its friend declaration, like so:

    template<typename T> void buildTree(TreeNode<T>* & tree);

    Afterwards, make sure you actually implement the function.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    I added the declaration before the class Tree.
    The function is implemented as well.

    I am getting error: friend declaration âvoid buildTree(TreeNode<object>*&)â declares a non-template function
    in the friend declaration that is in bold in the code above.
    When implementing, I wrote:

    template<class object>
    void buildTree(blahblah)

    is that correct since it is a friend?
    Or should it be
    template<class object>
    void Tree<object>::buildTree(blah)

    I have tried several different ways and keep getting friend-related errors.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about showing some code that demonstrates the problem? I think that would be the easiest solution.
    In essence, you should have

    Code:
    template<typename T> void buildTree(TreeNode<T>* & tree);
    
    template<typename T>
    class Tree
    {
    	// ...
    	friend void buildTree(TreeNode<T>* & tree);
    	// ...
    };
    
    template<typename T> void buildTree(TreeNode<T>* & tree)
    {
    	// ...
    }
    Of course, if you put buildTree before Tree, then you don't need the declaration.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    Yes that is what I currently have.

    Code:
    template<class object>
    void buildTree(TreeNode<object> *&tree);
    
    template<class object>
    class Tree
    {
    private:
      TreeNode<object> *root;
    public:
      Tree();
      ~Tree();
      Tree(const Tree<object> &rhs);  // copy
      void operator=(const Tree<object> &rhs);
      void copyconst(TreeNode<object> *orig, TreeNode<object> *&rhs);
      void makeEmpty(TreeNode<object> *&tree);
      bool isEmpty()const;
      void expTree(Tree<object> &expression);
      friend void buildTree(TreeNode<object> *&tree); // line 54
      void printTree(TreeNode<object> *&tree)const;
    };
    
    template<class object>
    void buildTree(TreeNode<object> *&tree)
    {
      // code..
    }
    The error I get is:
    warning: friend declaration âvoid buildTree(TreeNode<object>*&)â declares a non-template function
    302hw4code2.cpp:54: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

  6. #6
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Maybe it is a bug, but what Elysia posted, essentially the following program, fails to compile.
    Code:
    template<typename T> void foo();
     
    template<typename T>
    class Bar
    {
        T t;
        friend void foo();
    };
     
    template<typename T> void foo()
    {
        Bar<int> b;
        b.t = 6;
    }
    int main()
    {
        foo<int>();
        return 0;
    }

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Ah, you've run afoul of the template friends madness.

    Change:
    friend void buildTree(TreeNode<T>* & tree); // line 54
    to
    friend void buildTree <> (TreeNode<T>* & tree); // line 54

    And it should compile.
    You might find more information here: http://www.parashift.com/c++-faq-lit...html#faq-35.16
    Last edited by Elysia; 10-19-2011 at 03:14 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    I will try in the morning. Thanks!

  9. #9
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    So my solution to rid my code of friend-related errors was to implement the function in the class itself. My updated class is as follows:

    Code:
    template<class object>
    class Tree
    {
    private:
      TreeNode<object> *root;
    public:
      Tree();
      ~Tree();
      Tree(const Tree<object> &rhs);  // copy
      void operator=(const Tree<object> &rhs);
      void copyconst(TreeNode<object> *orig, TreeNode<object> *&rhs);
      void makeEmpty(TreeNode<object> *&tree);
      bool isEmpty()const;
      friend void expTree(Tree<object> *&expression){
        buildTree(expression.root);
      }
      void buildTree(TreeNode<object> *&tree);
      void printTree(TreeNode<object> *&tree)const;
    };
    BUT, now I am getting error: 224: error: âexpTreeâ was not declared in this scope

    Here is what that error refers to:

    Code:
      
    int main()
    {
      Tree<string> *T;
      cout << "Enter postfix expression to convert:" << endl;
      expTree(*&T);  // line 224
      return 0;
    }
    Is this part of the same problem that I just have to play around with?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It works fine for me:
    Code:
    #include <string>
    #include <iostream>
    
    template<class object>
    class TreeNode {};
    
    template<class object>
    class Tree
    {
    private:
    	TreeNode<object> *root;
    public:
    	Tree();
    	~Tree();
    	Tree(const Tree<object> &rhs);  // copy
    	void operator=(const Tree<object> &rhs);
    	void copyconst(TreeNode<object> *orig, TreeNode<object> *&rhs);
    	void makeEmpty(TreeNode<object> *&tree);
    	bool isEmpty()const;
    	friend void expTree(Tree<object> *&expression){
    		//buildTree(expression.root);
    	}
    	void buildTree(TreeNode<object> *&tree);
    	void printTree(TreeNode<object> *&tree)const;
    };
    
    int main()
    {
    	Tree<std::string>* T;
    	std::cout << "Enter postfix expression to convert:" << std::endl;
    	expTree(T);  // line 224
    	return 0;
    }
    In case that doesn't work, post the minimal amount of compilable code that demonstrates the problem.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Code:
    expTree(*&T);
    That looks pretty redundant and I wouldn't name a variable T, since you're already using T as a template parameter.

    Code:
    Tree<string> *mytree;
    expTree(mytree);
    That should compile. I think the argument is the right type.

    edit - of course, Elysia ninja posts. Darn!

  12. #12
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    @whiteflags Yes. I remember posting this code in frustration, I've fixed the type long ago when I had a brief moment of clarity. Haha

    So, It still doesnt compile for me. Maybe my compiler doesn't like it.
    Here is the only error I am getting:

    In function `main':
    302hw4code2.cpp.text+0xae): undefined reference to `void expTree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(Tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >*&)'
    collect2: ld returned 1 exit status


    the only piece of code that's relevant I have already posted. but for this error, these are the classes I currently have:

    Code:
    #include<iostream>
    #include<string>
    using namespace std;
    
    template<class object> class Tree;
    template<class object> void expTree(Tree<object> *&T);
    
    template<class object>
    struct Node
    {
      object info;
      Node *next;
      Node<object>():info(0), next(NULL) {}
      Node<object>(const object &element, Node *n = NULL):
        info(element), next(n){}
    };
    template<class object>
    class Stack
    {
    public:
      Stack();
      ~Stack();
      void makestackempty();
      bool stackEmpty() const;
      void push(object &item);
      void pop (object &item);
      void printStack() const;
    private:
      Node<object> *top;
    };
    template<class object>
    struct TreeNode
    {
      object info;
      TreeNode *right;
      TreeNode *left;
      TreeNode()
      {}
    };
    
    template<class object>
    class Tree
    {
    private:
      TreeNode<object> *root;
    public:
      Tree();
      ~Tree();
      Tree(const Tree<object> &rhs);  // copy
      void operator=(const Tree<object> &rhs);
      void copyconst(TreeNode<object> *orig, TreeNode<object> *&rhs);
      void makeEmpty(TreeNode<object> *&tree);
      bool isEmpty()const;
      friend void expTree(Tree<object> *&T){
        buildTree(T.root);
      }
      void buildTree(TreeNode<object> *&tree);
      void printTree(TreeNode<object> *&tree)const;
    };
    and the main, even with little tweaks.
    Code:
    int main()
    {
      Tree<std::string> *T;
      std::cout << "Enter postfix expression to convert:" << std::endl;
      expTree(T);
      return 0;
    }
    My solution for now is i've written a new code with only one struct, and no templates. haha. It compiles. Sad code but ive gotten no stubborn errors. Working code is better than noncompiling code!

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, dunno what to say... Visual C++ and Comeau both compile fine.
    Of course, Comeau doesn't check for linker errors...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Aug 2011
    Posts
    28
    Yea, I've posted in 3 different forums and haven't been able to get it to compile. I know my implementation logic stuff is correct, because when I rewrote it without the mess it compiled fine.
    g++ doesn't like me.

    Thank you forum people.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Switch compiler?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Friend Functions
    By rculley1970 in forum C++ Programming
    Replies: 5
    Last Post: 03-25-2007, 03:25 AM
  2. Friend functions
    By JeremyCAFE in forum C++ Programming
    Replies: 2
    Last Post: 02-12-2006, 08:08 PM
  3. Friend functions
    By volyx in forum C++ Programming
    Replies: 3
    Last Post: 08-01-2004, 08:44 PM
  4. trouble with friend functions/classes
    By nextus in forum C++ Programming
    Replies: 2
    Last Post: 03-13-2003, 05:36 PM
  5. friend functions
    By The Dog in forum C++ Programming
    Replies: 2
    Last Post: 07-14-2002, 08:55 AM