【问题标题】:Template parameter name hiding模板参数名称隐藏
【发布时间】:2015-06-04 10:26:16
【问题描述】:

我最近被(简体)咬了

struct Base {
    typedef char T;
};

template<typename T>
struct Foo : Base {
    T x[50];  // This is Base::T, not the template parameter
};

换句话说,类成员名称隐藏了模板参数(即使来自基类,因此在本地上下文中并不完全明显)。

做了一些实验,我发现:

struct Base {
    typedef char T;
};

template<typename T, typename B>
struct Foo : B {
    T x[50];  // This T is the template parameter,
              // even passing Base as B
};

这个明显荒谬的规则背后的基本原理(如果有的话)是什么?

我能想到的唯一方法是给出丑陋的模板参数名称,这也意味着不使用保留名称就不可能安全地编写模板(因为模板中使用的类可能会与参数名称冲突......请注意许多 C++ 代码为私有成员使用丑陋的名称)。

PS:我没有深入研究这个问题的标准,但 g++ 和 clang++ 都同意这种行为,所以我不认为这是一个错误。

PPS:在实际代码中,被隐藏的模板参数被命名为tid,它是一个整数而不是一个类型。 -Wall 不足以通知隐藏,我在使用 valgrind 调试几个小时后发现了它。

【问题讨论】:

  • 你用不同的编译器试过了吗?很高兴知道这是与实现相关、标准中的粗心还是实际意图。
  • @stefaanv 这是标准化行为,当然不是粗心大意。
  • 可能是因为依赖名和独立名。见this也许对你有帮助。
  • 单字母变量是个坏主意。我什至避免使用一个字母模板变量。他们隐藏意图。一封信不会向读过密码的可怜的混蛋透露任何信息。包括你自己在内的那个可怜的混蛋。这样做是为了避免被咬。
  • @PhilipStuyck:在实际代码中,被隐藏的模板参数被命名为tid,它是一个整数而不是一个类型。 -Wall 不足以通知隐藏,我在使用 valgrind 调试几个小时后发现了它。

标签: c++ templates language-lawyer name-lookup name-hiding


【解决方案1】:

此规则(在 [temp.local]/9 中指定)是 11 年前创建的开放核心语言问题的主题 - core issue #459。 CWG 对此进行了彻底的讨论。关于意图,Mike Miller 提到了这一点

当前规范的基本原理非常简单:

  • “除非在派生类中重新声明,否则基类的成员也被视为派生类的成员。” (10 [class.derived] 第 2 段)

  • 在类范围内,成员隐藏非成员。

就是这样。因为模板参数不是成员,它们是 由成员名称隐藏(无论是否继承)。我不觉得 “奇怪”,甚至特别令人惊讶。

理由:

我们对更改表示同情,但当前规则直接不属于查找规则,因此它们并没有“错误”。让私人成员不可见也可以解决这个问题。我们愿意查看提出该问题的论文。[..]
CWG 决定在没有更详细地探讨该问题的论文的情况下目前不考虑对现有规则进行更改。强>

很遗憾,目前还没有这样的论文,所以这个规则一直持续到今天。

【讨论】:

  • 感谢您的回答。它确实是标准化的,但仍然是一个问题。
  • 对于任何感兴趣的人,两年后,问题仍然存在,状态保持不变。
猜你喜欢
  • 2011-08-24
  • 2016-10-26
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多