Thread: Issue with namespace function declared as friend of class

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Unhappy Issue with namespace function declared as friend of class

    I'm having an issue with a namespace function which was declared as a friend of class. The namespace definition is above the class definition, but contains only function declarations (and not their definitions). The namespace functions' definitions are below the class definition.
    Now, the issue is, one of my namespace functions (which is declared as a friend by the class) attempt to access a private member of the class, but when I try to compile it, it complains that the private variable I'm trying to access "was not declared in this scope".

    Any ideas why the 'friend' declaration is not working right, and not allowing access to the private members of the class?

    Thanks in advance.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Post the shortest and simplest program that you expect will compile but which demonstrates this error.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Posting some code will increase the chance of getting more people to try figuring out an answer i think

    Searching this forum a bit i found this ,which i think it explains things good Friend Functions and Friend Classes - Cprogramming.com

    EDIT->i let laserlight post before me,because ladies first is a rule

  4. #4
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    Post the shortest and simplest program that you expect will compile but which demonstrates this error.
    C_html4_tags.h:
    Code:
    //STL Modules:
    #include <string>
    #include <vector>
    
    //My modules:
    #include "modules/C_html4_attributes/C_html4_attributes.h"
    #include "C_ENUM_tag_converted_to_strings.h"
    
    namespace N_init_class_members {
    
        typedef std::vector<S_html_attr_value> TYPE_attr_values;
    
        void initAttr(C_html4_attributes::ENUM_attr attr_ET, S_html_attr& attr, const std::string& desc, const std::vector<S_browser>& supportedBrowsers,
                      const std::map<S_browser, TYPE_attr_values>& supportedAttrValues, bool required, bool deprecated,
                      const std::vector<std::string>& notes, const std::vector<std::string>& tips);
    
        void initSingleTag(S_html_tag& singleTag, const char* tagName, const std::vector<S_html_attr>& supportedAttrs);
    
        void initStartTag(S_html_tag& startTag, const char* tagName, const std::vector<S_html_attr>& supportedAttrs);
    
        void initEndTag(S_html_tag& endTag, const char* tagName);
    
    }
    
    class C_html4_tags {
           public:
                friend void N_init_class_members::initAttr(C_html4_attributes::ENUM_attr attr_ET, S_html_attr& attr, const std::string& desc, const std::vector<S_browser>& supportedBrowsers,
                                                     const std::map<S_browser, N_init_class_members::TYPE_attr_values>& supportedAttrValues, bool required, bool deprecated,
                                                     const std::vector<std::string>& notes, const std::vector<std::string>& tips);
    
      private:
           C_html4_attributes C_html4_attributes_obj;
    };
    
    void N_init_class_members::initAttr(C_html4_attributes::ENUM_attr attr_ET, S_html_attr& attr, const std::string& desc, const std::vector<S_browser>& supportedBrowsers,
                                        const std::map<S_browser, N_init_class_members::TYPE_attr_values>& supportedAttrValues, bool required, bool deprecated,
                                        const std::vector<std::string>& notes, const std::vector<std::string>& tips) {
    
        try {
           C_html4_attributes_obj.setDescOfAttr(attr_ET, desc);
           C_html4_attributes_obj.setSupportedBrowsersOfAttr(attr_ET, supportedBrowsers);
           C_html4_attributes_obj.setSupportedAttrValuesOfAttr(attr_ET, supportedAttrValues);
           C_html4_attributes_obj.setRequiredOfAttr(attr_ET, required);
           C_html4_attributes_obj.setDeprecatedOfAttr(attr_ET, deprecated);
           C_html4_attributes_obj.setNotesOfAttr(attr_ET, notes);
           C_html4_attributes_obj.setTipsOfAttr(attr_ET, tips);
           attr = C_html4_attributes_obj.getAttr(attr_ET);
        }
    
        catch (const char* exc) {
           C_ENUM_attr_converted_to_strings enum_conversion_obj;
           int attr_enumerator_value = attr_ET;
           std::string attr_enumerator_name;
           attr_enumerator_name = enum_conversion_obj.getNameOfEnumerator(enum_conversion_obj.castIntToEnumerator<C_ENUM_attr_converted_to_strings::ENUM_attr>(attr_enumerator_value));
           std::string exc_str = "Error! Call to N_init_class_members::initAttr().\n"
                                 "You passed to parameter 1, 'attr_ET', the attribute\n"
                                 "type name '" + attr_enumerator_name + "', so that\n"
                                 "is the attribute which you failed to initialize.\n"
                                 "This function has called several different member\n"
                                 "functions of a C_html4_attributes class object.\n"
                                 "One of these reported the following exception:\n\n";
           exc_str += exc;
           throw (exc_str.c_str()); //re-throw exception
        }
    
    }
    As you can see, I declared the namespace function "N_init_class_members::initAttr()" as a friend in the C_html4_tags class, and yet, the compiler still says that the "C_html4_attributes_obj" (which is a private member of C_html4_tags) "was not declared in this scope".
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  5. #5
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by std10093 View Post
    Posting some code will increase the chance of getting more people to try figuring out an answer i think

    Searching this forum a bit i found this ,which i think it explains things good Friend Functions and Friend Classes - Cprogramming.com

    EDIT->i let laserlight post before me,because ladies first is a rule
    Right. I read that page as well as some other ones on the web pertaining to namespaces and friend functions before posting, but I couldn't find any reason why my code wouldn't work.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I asked for a program so that I can compile it myself. I asked for something short and simple because in the process of reducing the problem, you increase your own chances of discovering what is the reason for the problem, and then arriving at your own solution.

    Anyway, the problem is that N_init_class_members::initAttr is accessing a object named C_html4_attributes_obj that does not appear to be belong to a C_html4_tags object. I would have expected you to pass a C_html4_tags object to that function, which then accesses the C_html4_attributes_obj member.

    EDIT:
    I found this out after I started by reducing your program to:
    Code:
    namespace N_init_class_members {
        void initAttr();
    }
    
    class C_html4_tags {
    public:
        friend void N_init_class_members::initAttr();
    private:
        C_html4_attributes C_html4_attributes_obj;
    };
    
    int main()
    {
    }
    At this point, I needed to find out how does initAttr access the member of the C_html4_tags object, upon which I discovered that there was no such object. Thus, the friendship does not apply.
    Last edited by laserlight; 09-22-2012 at 12:11 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    The problem is that you have not declared a C_html4_attributes_obj in this scope.Well i did say nothing different from the compiler now

    You have to pass an argument of the class that you want to see it's private part.Then the friend key word will let you ,do this

    Take this example and i think you are going to understand what i mean
    Code:
    class Count
    {
    friend void setX(Count&, int); // friend declaration
    public:
    Count() { x= 0; }
    void print() const { cout << x << endl; }
    private:
    int x;
    };
    void setX(Count& c, int val)
    {
    c.x = val; // Access to private part
    }
    int main()
    {
    Count counter;
    counter.print();
    setX(counter,8);
    counter.print();
    return 0;
    }
    EDIT->laserlight is first again ..

  8. #8
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by laserlight View Post
    I asked for a program so that I can compile it myself. I asked for something short and simple because in the process of reducing the problem, you increase your own chances of discovering what is the reason for the problem, and then arriving at your own solution.

    Anyway, the problem is that N_init_class_members::initAttr is accessing a object named C_html4_attributes_obj that does not appear to be belong to a C_html4_tags object. I would have expected you to pass a C_html4_tags object to that function, which then accesses the C_html4_attributes_obj member.

    EDIT:
    I found this out after I started by reducing your program to:
    Code:
    namespace N_init_class_members {
        void initAttr();
    }
    
    class C_html4_tags {
    public:
        friend void N_init_class_members::initAttr();
    private:
        C_html4_attributes C_html4_attributes_obj;
    };
    
    int main()
    {
    }
    At this point, I needed to find out how does initAttr access the member of the C_html4_tags object, upon which I discovered that there was no such object. Thus, the friendship does not apply.
    Duh. You're right. I forgot to create a C_html4_tags object.
    However, once realizing I would need this in order to make the friend feature work, I decided that this would be a dumb thing to do, since the C_html4_tags object is quite big, and creating one of those for each attribute initialized from the constructor would take forever, as well as recursively doing the same thing, and even if I passed the C_html4_tags object as a reference or a pointer to the function (maybe by passing the "this" pointer from the constructor of C_html4_tags each time I call N_init_class_members::initAttr() ), there would still be multiple problems. So I decided that the best approach to solve the problem was forget using friendship at all, and instead just create another C_html4_attributes object inside the initAttr() function. I think there was a reason I was wanting to use the same object before, but I don't remember what it was, and after looking at the code again, I think this approach will work, so I'm going to do that.

    So thanks.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Friend of namespace or of namespace function?
    By Programmer_P in forum C++ Programming
    Replies: 18
    Last Post: 03-13-2011, 06:46 PM
  2. friend function template class declaration error
    By -EquinoX- in forum C++ Programming
    Replies: 2
    Last Post: 11-20-2009, 01:00 PM
  3. Replies: 11
    Last Post: 05-02-2009, 09:23 AM
  4. Problem with friend class declaration in a namespace
    By Angus in forum C++ Programming
    Replies: 2
    Last Post: 12-09-2008, 01:29 PM
  5. Replies: 5
    Last Post: 06-04-2002, 02:33 PM