Why is private member template accessible outside class?

Hi,

I just happened to find that a nested private template class can be accessed directly outside the enclosing class using a using alias:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace ns {

    class __wrapper
    {
    private:
        template <typename T>
        class __tklass {};

        class __klass {};
    };

    template <typename T>
    using tklass = __wrapper::__tklass<T>; // Expected error but compiles OK :(

    using klass = __wrapper::__klass;      // Correctly throws "__klass is private" error

}

int main()
{
    ns::tklass<int> v1;                    // No error generated here as well

    ns::__wrapper::__tklass<int> v3;       // Correctly throws "__tklass is private" error
    ns::__wrapper::__klass v4;             // Correctly throws "__klass is private" error
}


I was hoping to see a "__wrapper::__tklass is private" error message in the first using statement as well as during the instantiation of ns::tklass, but no error is issued. I tried this on gcc-4.9.2, clang-3.5.0 and visual_studio 2013 express.

So my question is why exactly doesn't the compiler flag tklass as an error? Is it allowed by the standard? If so, wouldn't that be a serious access violation?
Last edited on
It comes up at a error for me in Visual Studios 2012.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
namespace ns {

    class wrapper
    {
        private:
            template <typename T>
            class tklass {};

            class klass {};

            friend int foo() ;
    };

    template <typename T>
    using tklass = wrapper::tklass<T>; // Expected error but compiles OK :(
    // this, by itself, is not an error.
    // (the template alias can be used by a member or friend of wrapper)

    // fine: friend of wrapper has access to wrapper::tklass<>
    int foo() { tklass<int> this_is_fine ; return sizeof(this_is_fine) ; }
}

int main()
{
    ns::tklass<int> v1; // **** AFAIK, this should be an error
                        // (not sure if it falls under  "no diagnostic required")

    ns::wrapper::tklass<int> v2; // **** just as this is an error (diagnosed)
}


Note: names like __wrapper are reserved for the implementation.
Certain sets of names and function signatures are always reserved to the implementation:
— Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

Last edited on
Topic archived. No new replies allowed.