为什么可以在类外部访问私有成员模板

为什么可以在类外部访问私有成员模板

本文介绍了C ++ 11:为什么可以在类外部访问私有成员模板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是偶然发现,可以使用using指令直接在封闭的类外部访问嵌套的私有模板类:

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;      // "Error: __klass is private"

int main()
{
    tklass<int> v1;                     // Expected error but compiles OK

    // wrapper::__tklass<int> v3;       // "Error: __tklass is private"
    // wrapper::__klass v4;             // "Error: __klass is private"
}

标记为错误:__ xxx是私有的"的行在未注释时正确报告错误.但是带有tklass的行将被编译,而不会受到编译器的任何抱怨.

那么,尽管wrapper::__tklass是私有的,为什么为什么编译器仍不将tklass标记为错误呢?是标准允许的任何机会吗?如果是这样,那不算是严重的访问冲突吗?

我在gcc-4.9.2,clang-3.5.0和Visual Studio 2013 Express上进行了尝试. GCC命令行:

g++ -std=c++11 -pedantic -Wall -Wextra -Wshadow myfile.cpp
解决方案

这绝对是一个编译器错误,并且实际上是已经存在一段时间的已知错误:GCC#47346 (2011年1月首次报道)和 C#15914 (2013年5月首次报道).您的__tklass显然是private,并且模板别名未标记为friend,因此这应该是一个简单的访问错误.

最简单的复制来自Clang示例附件,该版本可以在gcc 4.9.2和clang 3.5.0上进行编译,尽管绝对不能在以下两种情况下进行编译:

class A
{
  class B {};
};

template<typename>
using T = A::B;

T<void> t;

在这方面,Clang严格比GCC更好,因为此特定错误似乎仅在模板别名下才会发生.一个解决方法"(如果在某些情况下需要编译器允许错误地使用它……)将恢复为C ++ 11之前的模板别名:

template <typename>
struct T {
    using type = A::B;
};

T<void>::type t;

该代码无法正确地使用clang编译(错误:"B"是"A"的私有成员),但仍可以使用gcc正常编译.

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

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;      // "Error: __klass is private"

int main()
{
    tklass<int> v1;                     // Expected error but compiles OK

    // wrapper::__tklass<int> v3;       // "Error: __tklass is private"
    // wrapper::__klass v4;             // "Error: __klass is private"
}

The lines marked "Error: __xxx is private" correctly report an error when uncommented. But the lines with tklass get compiled without any complaint from the compiler.

So why exactly doesn't the compiler flag tklass as error despite wrapper::__tklass being private? Is it by any chance allowed by the standard? If so, wouldn't that be considered a serious access violation?

I tried this on gcc-4.9.2, clang-3.5.0 and visual studio 2013 express. GCC command line:

g++ -std=c++11 -pedantic -Wall -Wextra -Wshadow myfile.cpp
解决方案

This is definitely a compiler bug, and actually one that has been known for quite some time: GCC #47346 (first reported in Jan 2011) and Clang #15914 (first reported May 2013). Your __tklass is clearly private, and the template alias is not marked friend, so this should be a simple access error.

The simplest reproduction is from the Clang example attachment, this version compiles on both gcc 4.9.2 and clang 3.5.0, though should definitely compile on neither:

class A
{
  class B {};
};

template<typename>
using T = A::B;

T<void> t;

Clang is strictly better than GCC on this front however, as this particular bug seems to occur only with template aliases. A "workaround" (if you need such a thing for cases that the compiler allows incorrectly...) would be to revert back to pre-C++11 template aliasing:

template <typename>
struct T {
    using type = A::B;
};

T<void>::type t;

That code correctly fails to compile with clang (error: 'B' is a private member of 'A'), but still compiles fine with gcc.

这篇关于C ++ 11:为什么可以在类外部访问私有成员模板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 08:17