模板参数名称隐藏
Template parameter name hiding
我最近被(简体)咬了
struct Base {
typedef char T;
};
template<typename T>
struct Foo : Base {
T x[50]; // This is Base::T, not the template parameter
};
换句话说,class 成员名称隐藏了一个模板参数(即使来自基础 class,因此在本地上下文中并不完全明显)。
做一些实验我发现:
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
};
这个看似荒谬的规则背后的基本原理(如果有的话)是什么?
我能想到的唯一出路是给出丑陋的模板参数名称,这也意味着不使用保留名称就不可能安全地编写模板(因为模板中使用的 class 可能会与参数名称冲突...请注意,许多 C++ 代码对私有成员使用丑陋的名称)。
PS:我没有深入研究这个问题的标准,但是 g++ 和 clang++ 都同意这种行为,所以我不认为这是一个错误。
PPS:在实际代码中,被隐藏的模板参数被命名为tid
,并且是一个整数而不是类型。 -Wall
不足以通知隐藏,我在使用 valgrind 调试了几个小时后发现了它。
此规则(在 [temp.local]/9) is subject of an open core language issue created over 11 years ago - core issue #459 中指定。CWG 对此进行了彻底讨论。关于意图,Mike Miller 提到
The rationale for the current specification is really very simple:
“Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class.” (10
[class.derived] paragraph 2)
In class scope, members hide nonmembers.
That's it. Because template parameters are not members, they are
hidden by member names (whether inherited or not). I don't find that
“bizarre,” or even particularly surprising.
理由:
We have some sympathy for a change, but the current rules fall straightforwardly out of the lookup rules, so they're not “wrong.” Making private members invisible also would solve this problem. We'd be willing to look at a paper proposing that.[..]
The CWG decided not to consider a change to the existing rules at this time without a paper exploring the issue in more detail.
遗憾的是还没有这样的论文被写出来,所以这个规则一直持续到今天。
我最近被(简体)咬了
struct Base {
typedef char T;
};
template<typename T>
struct Foo : Base {
T x[50]; // This is Base::T, not the template parameter
};
换句话说,class 成员名称隐藏了一个模板参数(即使来自基础 class,因此在本地上下文中并不完全明显)。
做一些实验我发现:
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
};
这个看似荒谬的规则背后的基本原理(如果有的话)是什么?
我能想到的唯一出路是给出丑陋的模板参数名称,这也意味着不使用保留名称就不可能安全地编写模板(因为模板中使用的 class 可能会与参数名称冲突...请注意,许多 C++ 代码对私有成员使用丑陋的名称)。
PS:我没有深入研究这个问题的标准,但是 g++ 和 clang++ 都同意这种行为,所以我不认为这是一个错误。
PPS:在实际代码中,被隐藏的模板参数被命名为tid
,并且是一个整数而不是类型。 -Wall
不足以通知隐藏,我在使用 valgrind 调试了几个小时后发现了它。
此规则(在 [temp.local]/9) is subject of an open core language issue created over 11 years ago - core issue #459 中指定。CWG 对此进行了彻底讨论。关于意图,Mike Miller 提到
The rationale for the current specification is really very simple:
“Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class.” (10 [class.derived] paragraph 2)
In class scope, members hide nonmembers.
That's it. Because template parameters are not members, they are hidden by member names (whether inherited or not). I don't find that “bizarre,” or even particularly surprising.
理由:
We have some sympathy for a change, but the current rules fall straightforwardly out of the lookup rules, so they're not “wrong.” Making private members invisible also would solve this problem. We'd be willing to look at a paper proposing that.[..]
The CWG decided not to consider a change to the existing rules at this time without a paper exploring the issue in more detail.
遗憾的是还没有这样的论文被写出来,所以这个规则一直持续到今天。