user11712295
user11712295

Reputation:

How to make function friend of local class?

Please read the code to know the problem :

#include <iostream>

void fun(int value)
{
    //starts local class definition
    class test
    {
        int x;
    public:
        test(int a) : x(a) {}
        void display() const
        {
            std::cout << "x = " << x << std::endl;
        }
    };
    //end of the definition
    test t1(value);
    t1.display();
    //if we write the statement t1.x=100; here .It will give us an error
    //because we can not access the private members from the enclosing function
    //now what should I do if I want to access the private members of the test class from fun function
}
int main()
{
    fun(5);
}

Should I make the fun function as friend for the local class(test). I was reading a book and there was said that we can achieve this by declaring the enclosing function as a friend. Now my problem is this I don't know how to make the enclosing function as a friend of the local class. Please, someone tell me how can I do so.

Upvotes: 1

Views: 285

Answers (4)

Jarod42
Jarod42

Reputation: 217135

Qualified call friend void ::fun(int); is a way:

void fun(int value)
{
    //starts local class definition
    class test
    {
        friend void ::fun(int);
        int x;
    public:
        test(int a)
        {
            x=a;
        }
        void display()
        {
            std::cout << "x = " << x << std::endl;
        }

    };
    //end of the definition
    test t1(value);
    t1.display();
    t1.x = 42;
    t1.display();
}

Demo

Notice than some old version of g++ reject it.

Upvotes: 2

Zopolis4
Zopolis4

Reputation: 145

Note that this bug has now been fixed in GCC, and backported to versions 10 and up.

Upvotes: 0

eerorika
eerorika

Reputation: 238311

Should I make the fun function as friend for the local class(test)

It's unclear whether you should. It is often a good idea to avoid breaking the encapsulation that private members offer. Or conversely, if the encapsulation isn't needed, then maybe it would be simpler for the member to be public. But let's instead consider whether you could...

Standard says (quoting latest draft):

[class.friend]

If a friend declaration appears in a local class ([class.local]) and the name specified is an unqualified name, a prior declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope. For a friend function declaration, if there is no prior declaration, the program is ill-formed. ...

If I interpret this legalese correctly, no unqualified name outside of the function body of fun can be looked up. As far as I know, the declaration of fun itself is outside of that scope. However also as far as I know, nothing should prevent you from re-declaring the function:

void fun(int value)
{
    void fun(int); // (re)declaration within innermost enclosing non-class scope

    class test
    {
        friend void fun(int); // the friend declaration

This appears to work in Clang and MSVC, but not in GCC unfortunately, which still doesn't allow access to the private member. This may be a GCC bug.

Another option would be to declare the friend with a qualified name:

class test
{
    friend void ::fun(int); // qualified name

In which case the restriction above wouldn't apply. Unfortunately, GCC doesn't accept this either, and without the local re-declaration produces a diagnostic:

error: friend declaration 'void fun(int)' in local class without prior local declaration

This looks like a separate bug, which reproduces whether declaring ::fun or any other qualified function name as friend. I found an existing bugreport: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69410

Upvotes: 2

user10046520
user10046520

Reputation:

First declare the function

void fun(int);

Then in class :

public:
friend void ::fun(int  );

Upvotes: 0

Related Questions