为什么通常的访问控制检查适用于通过模板参数访问时用于指定显式实例化的名称?

2024-02-29

C++11/14 标准在注释 14.7.2/12 [temp.explicit] 中声明了以下内容:

通常的访问检查规则不适用于用于指定的名称 显式实例化。 [ 注意:特别是模板参数 以及函数声明符中使用的名称(包括参数类型、 返回类型和异常规范)可以是私有类型或对象 通常无法访问,并且模板可能是成员 通常无法访问的模板或成员函数。 ——尾注]

如果我可以实例化模板,我希望能够使用它。

我尝试使用 gcc-4.8.2,当我访问显式命名的类的私有成员时,我得到了预期的行为。但是,当我通过模板参数访问私有成员时,访问检查规则确实适用。这是 gcc 中的错误,还是我遗漏了什么?

在下面的代码中,“成功”和“失败”之间的唯一区别是前者通过“A”直接访问私有成员,而后者通过模板参数“T”访问它。编译器抱怨 privateFoobar 在该上下文中是私有的。

#include <iostream>
#include <string>

struct A
{
private:
    std::string privateFoobar() {return "private foobar!";}
};

typedef std::string (A::*Foobar)();

template <class Type, Type value>
struct Access
{
    static Type getValue() {return value;}
};

template <class T>
struct IndirectAccess
{
    static Foobar succeeds() {return Access<Foobar, &A::privateFoobar>::getValue();}
    static Foobar fails() {return Access<Foobar, &T::privateFoobar>::getValue();}
};

template class Access<Foobar, &A::privateFoobar>;

int main() {
    std::cout << (A().*Access<Foobar,&A::privateFoobar>::getValue())() << std::endl;
    std::cout << (A().*IndirectAccess<A>::succeeds())() << std::endl;
    std::cout << (A().*IndirectAccess<A>::fails())() << std::endl;
}

如果您想知道这种可被解雇的罪行的用例是什么:创建一个框架,该框架将根据所选组件的实现选择自动配置应用程序。


显式实例化必须在命名空间范围内,这意味着类的私有成员通常无法访问。如果没有您引用的规则,这是不可能的:

class Foo
{
private:
  struct Bar;

  template<typename T> class Baz { };

public:
  void f();  // does things with Baz<Bar>
};

// explicit instantiation declaration
extern template class Foo::Baz<Foo::Bar>;

如果没有这条规则,我将无法命名Foo::Bar甚至Foo::Baz在命名空间范围内,因为这些名称是私有的Foo.

因为我其实不是using Foo::Bar or Foo::Baz在这里,只是引用它们的名称来告诉编译器我正在其他地方实例化模板,不存在真正的访问冲突(尽管可以使用此规则来执行非常鬼鬼祟祟的把戏 https://gist.github.com/dabrahams/1528856否则不可能)。

同样,当我在其他文件中编写显式实例化定义时,我需要能够在命名空间范围内再次引用私有名称。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么通常的访问控制检查适用于通过模板参数访问时用于指定显式实例化的名称? 的相关文章

随机推荐

  • 使用 classpathentry 包含多个 jar

    我有一个 eclipse 的 classpath 文件 如下所示
  • Laravel 3 - 如何验证复选框数组,至少选中 1 个?

    我开始学习 Laravel 并且仍在学习曲线上 现在我从 Laravel 3 开始 但一旦我开始工作 很可能会将我的项目切换到 Laravel 4 现在的问题是 如何验证复选框数组 我想验证组内至少有 1 个复选框已启用 选中 我在 Lar
  • Bulma 导航栏和 VueJS 路由器活动链接

    我已经开始使用布尔玛0 7 1 and VueJs 2 5 17 现在 我正在使用 Vue 路由器组件 并且我希望每当我位于链接表示的 页面 上时 将导航栏中的按钮设置为活动状态 我的代码如下
  • 由于冲突,无法删除一些未标记的 docker 镜像

    我无法显式删除一些未标记的 docker 映像 具体来说 那些带有标签的
  • C#/.NET:在 C# 中创建动态视觉效果

    注意 我不太确定如何标题或标记这个问题 所以如果您有任何想法 请帮忙 我目前正在设想一些可能的项目 涉及动态渲染某些东西 作为假设的例子 无论是点 线 文本还是五线谱上的音符 但是 如果我要承担这些项目 我 我不太确定如何实现这个设计 我很
  • 在 C# 中验证 FQDN

    有人有正则表达式来验证合法的 FQDN 吗 现在 我使用这个正则表达式 1 254 d a zA Z0 9 1 63 a zA Z 2 但是 此正则表达式会导致 aa a 无效 而 aa aa 有效 有谁知道为什么 这是一个较短的模式 1
  • 如何查询所有子文档

    我从 MongoDb 和 nodejs 使用 mongoose 开始 我有一个收藏Stories 每个都可以有一个或多个Tags 是这样的 title The red fox content The red fox jumps away t
  • 使用 bootstrap 的 Angular 6 库

    我正在使用 Angular 6 库功能在 Angular 项目中创建 Angular 库https github com angular angular cli wiki stories create library https githu
  • 如何在图片下方写标题?

    我有两个图像需要保持内联 我想在每张图片下写一个标题
  • Ionic 3 - 每个页面都需要自己的模块吗?

    我是 Ionic 新手 试图了解如何组织中型应用程序 每个页面应该有自己的模块吗 或者将相似的页面分组到同一个模块中是否更好 有可能这样做吗 看来 IonicPageModule forChild 方法只接受一页 IonicPageModu
  • 将环境类与管道运行结合使用

    我正在使用环境类对管道使用估计器步骤 以便拥有自定义 Docker 映像 因为我需要一些apt get软件包能够安装特定的 pip 软件包 从日志中可以看出 与估计器的非管道版本不同 它完全忽略了环境变量的 docker 部分 很简单 这似
  • Microsoft AlwaysOn 故障转移解决方案和 Delphi

    我正在尝试制作一个 Delphi 应用程序来与 AlwaysOn 解决方案一起使用 我在谷歌上发现我必须使用MultiSubnetFailover True在连接字符串中 应用程序在Delphi XE3中编译并使用TADOConnectio
  • 什么是直接引用?

    严格模式规则之一 Annex C http ecma international org ecma 262 5 1 sec C 状态 When a delete运算符出现在严格模式代码中 语法错误被抛出 如果它一元表达式是对变量 函数参数或
  • 如何跟踪量角器正在等待哪些异步任务?

    我有一个中型 Angular 应用程序 由于某些原因 我的一些量角器测试在我的实时生产环境中运行时超时 我相当确定超时是由于量角器等待某些异步任务而发生的 我了解区域 并且我尝试将所有长时间运行的异步任务保留在 ngZone 之外 根据th
  • 如何让定时器准确? (Flash/ActionScript 3.0)

    我使用以下方法以 X 次 分钟发送声音 X 通过 bpm 确定 它是一个 NumericStepper 对象 var mainTimer Timer new Timer 60 bpm value 1000 0 mainTimer addEv
  • 使用 Visual Studio 2008 编辑 RDL 文件

    我已在两个工作站上安装了 SQL Server 2008 Express 在一台工作站上 它更新了 VS2008 安装 以便我可以创建包含 rdl 文件格式的报告的报告项目 在其他工作站上 VS2008只能创建 编辑 rdlc文件 报告编辑
  • string.Format() 给出“输入字符串的格式不正确”

    我在这里做错了什么 string tmp if UseImageFiles vCalHeader td img src 0 cal fastreverse gif width 13px height 9 style border 1px s
  • Pandas Fillna 多列与每列众数

    使用人口普查数据时 我想将两列 workclass 和 native country 中的 NaN 替换为这两列各自的模式 我可以轻松获得模式 mode df filter workclass native country mode 它返回
  • 使用 Javascript 将禁用属性添加到输入元素

    我有一个输入框 我希望禁用它并同时隐藏它以避免移植表单时出现问题 到目前为止 我有以下代码来隐藏我的输入 shownextrow click function this closest tr next show find longboxsm
  • 为什么通常的访问控制检查适用于通过模板参数访问时用于指定显式实例化的名称?

    C 11 14 标准在注释 14 7 2 12 temp explicit 中声明了以下内容 通常的访问检查规则不适用于用于指定的名称 显式实例化 注意 特别是模板参数 以及函数声明符中使用的名称 包括参数类型 返回类型和异常规范 可以是私