Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making an undefined class as friend, and defining it later

Making an unknown friend

template<typename T>
class List
{
protected:

    class a {
        int x;
        int y;
    private:
        friend class b;  // <------------ Why this is not an error? 
    };

    template <typename U > class b {  //If that is not a error this should be an error
        int z;
        U y;
    };

    public:
        List() {
            a* ptr = (a *)new unsigned char[sizeof(a)];
        }
};

int main() {
    List<int>  mylist;
}

Please go through this link, I have my questions as comments in the code. I am trying to make another class a friend of my class. But that class is not know at the time of making friend. What is the C++ rule that allows for it. Later I am defining that class in such a way that, it is incompatible with the friend declaration. Why is that not throwing an error. Thanks

like image 280
Saurabh Avatar asked Nov 25 '10 06:11

Saurabh


People also ask

How can a global non member function be declared as a friend to a class?

A function or class can't declare itself as a friend of any class. In a class definition, use the friend keyword and the name of a non-member function or other class to grant it access to the private and protected members of your class. In a template definition, a type parameter can be declared as a friend .

How do you define a friends class in C++?

A friend function is a special function in C++ which in-spite of not being member function of a class has privilege to access private and protected data of a class. A friend function is a non member function or ordinary function of a class, which is declared as a friend using the keyword “friend” inside the class.

How do you define a friends class in Java?

In object-oriented programming, a friend function, that is a "friend" of a given class, is a function that is given the same access as methods to private and protected data. A friend function is declared by the class that is granting access, so friend functions are part of the class interface, like methods.

Can a derived class be a friend of base?

Inheritance and Friendship in C++If a base class has a friend function, then the function doesn't become a friend of the derived class(es). For example, the following program prints an error because the show() which is a friend of base class A tries to access private data of derived class B.


2 Answers

Yes your code is invalid! This is an interesting show of how templates can change meaning of code in subtle ways. The following code is valid:

class List
{
public:
    class a {
        typedef int type;
        friend class b; // that's fine!
    };

    template <typename U > class b;
};

class b {
  List::a::type an_int; // allowed to access private member
};

Standard says at 7.3.1.2/3

If a friend declaration in a non-local class first declares a class or function83) the friend class or function is a member of the innermost enclosing namespace.

When is it a "first declared class"? It says that too there

When looking for a prior declaration of a class or a function declared as a friend, and when the name of the friend class or function is neither a qualified name nor a template-id, scopes outside the innermost enclosing namespace scope are not considered.

The lookup for "class b" is delegated from 7.1.5.3/2 to 3.4.4 which in turn delegates to unqualified name lookup at 3.4/7. All the question now is whether the template-name "b" is visible in the friend declaration class a. If it isn't, the name is not found and the friend declaration will refer to a new declared class at global scope. 3.3.6/1 about the scope of it says

The potential scope of a name declared in a class consists not only of the declarative region following the name’s declarator, but also of all function bodies, default arguments, and constructor ctor- initializers in that class (including such things in nested classes).

Ignoring a few pedantic points that would make this wording not apply to here (which were a defect but are fixed in the C++0x version of that paragraph which also makes this easier to read), this list does not include the friend declaration as an area where that template name is visible.

However, the friend was declared in a member class of a class template. When the member class is instantiated different lookup applies - the lookup for friend names declared in a class template! The Standard says

Friend classes or functions can be declared within a class template. When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

So the following code is invalid:

template<typename T>
class List
{
public:
    class a {
        typedef int type;
        friend class b; // that's fine!
    };

    template <typename U > class b;
};

// POI
List<int>::a x; 

When that causes List<int>::a to be implicitly instantiated, the name a is looked up at "// POI" as if there would have been an explicit specialization declared. In that case, the template List::b has already been declared, and this lookup will hit it and emit an error because it's a template and not a non-template class.

like image 196
Johannes Schaub - litb Avatar answered Sep 20 '22 23:09

Johannes Schaub - litb


//Run this- it now will compile for you

template <typename U > class b; //<----- forward declaration

template<typename T>
class List
{
protected:


        class a {
        int x;
        int y;
        private:
          friend class b<T>;  // <------------ Add <T>
        };
        template <typename U > class b { 
          int z;
          U y;
        };

        public:
        List() {
          a* ptr = (a *)new unsigned char[sizeof(a)];
        }
};

int main() {
    List<int>  mylist;

}
like image 28
Delashmate Avatar answered Sep 22 '22 23:09

Delashmate