Jon Ringle
Jon Ringle

Reputation: 143

C++ class template function can access nested class private member

The following code fails to compile as expected:

#include<iostream>
class Enclosing {
    int x;
    class Nested { int y; };

    void EnclosingFun(Nested *n) {
        std::cout << n->y;  // Compiler Error: y is private in Nested
    }
};

However, if I change EnclosingFun into a template member function, the compiler (gcc-7) doesn't complain about accessing y:

#include<iostream>
class Enclosing {      
    int x;
    class Nested { int y; };

    template <typename T>
    void EnclosingFun(Nested *n, T t) {
        std::cout << t << n->y;  // OK? Why?
    }      
};

Is this a bug in gcc? Or does c++ have different access rules for template member function to access nested classes?

Upvotes: 3

Views: 643

Answers (2)

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38528

It is not a bug in GCC. You do not call your function template, therefore the function is not instantiated, and it does not try to access the private member of the nested class. Try to call your function somewhere in a real function (not template) or try to refer it (implicit instantiation).

A function template by itself is not a type, or a function, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be determined so that the compiler can generate an actual function (or class, from a class template).

When code refers to a function in context that requires the function definition to exist, and this particular function has not been explicitly instantiated, implicit instantiation occurs.

template void Enclosing::EnclosingFun(Enclosing::Nested *n, int t); // instantiates the function for the second int parameter

Upvotes: 3

songyuanyao
songyuanyao

Reputation: 172924

Is this a bug in gcc? Or does c++ have different access rules for template member function to access nested classes?

No either.

According to the standard, §17.8.1 Implicit instantiation [temp.inst],

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.

That means, Enclosing::EnclosingFun() is not instantiated here. Adding the invocation to it would cause it to be instantiated, then you'll get the error, e.g.

prog.cc:8:30: error: 'int Enclosing::Nested::y' is private within this context
         std::cout << t << n->y;  // OK? Why?
                           ~~~^

LIVE

Upvotes: 5

Related Questions