为什么来自非依赖基 类 的非限定名称优于模板参数
Why are unqualified names from nondependent base classes favored over template parameters
C++ 标准规定来自非依赖基 类 的非限定名称优先于模板参数。这背后的原因是什么?
以下代码段来自 C++ 模板:
#include <iostream>
template <typename X>
class Base {
public:
int basefield;
using T = int;
};
class D1 : public Base<Base<void>> {
public:
void f() { basefield = 3; // works as normal
}
};
template <typename T>
class D2 : public Base<double> {
public:
void f() { basefield = 7; }
T strange; // what type am I ???
};
int main() {
D2<std::string> d;
d.strange = 100;
}
// what type am I ???
当在模板推导中查找不合格的名称时(如D2
),在模板参数列表之前考虑非依赖碱基。
在您的例子中,这意味着 class 模板 D2
的成员 strange
始终具有对应于 Base<double>::T
的类型 T
(这只不过是 int
).
您可以通过将 d.strange = 100;
更改为:
来确认这一点
d.strange = "100"; //this will give error saying: invalid conversion from ‘const char*’ to ‘Base::T’ {aka ‘int’}
以上语句产生错误:
invalid conversion from ‘const char*’ to ‘Base::T’
{又名 ‘int’}
这确认 strange
具有类型 int
.
What is the reasoning behind this?
标准这么说的一个原因可能是因为当开始查找名称时,它会从遇到名称的位置向上(向上)。现在,在向上搜索名称时,首先遇到 non-dependent Base,因此名称被解析为属于 non-dependent Base(显然 Base 必须有一个名称相同的成员正在查找)。也就是说,因为在这种情况下 Base 独立于模板参数并且因为它在查找发生时首先出现(从名称声明的点到向上的方向),所以 non-dependent基础优先。
另一方面,在依赖 Base 的情况下,必须首先知道模板参数才能知道依赖 Base。也就是说,在这种情况下,Base 并不独立于模板参数。因此,当查找发生时(再次向上方向),即使在模板参数之前遇到依赖 Base,依赖 Base 在知道模板参数之前是未知的。所以在这种情况下,模板参数优先是有意义的。
这是我目前对标准如此规定的推理。
不合格查找大致等同于在每个包含范围内尝试 合格 查找并保持第一个命中。由于 D2<…>::T
可以找到 Base<double>::T
,因此在 class 的范围内查找成功;对于词法引入的模板参数,该查找自然先于 outside the class.
此首选项还可避免在
之间进行不合格的名称更改
template<class T>
struct A : B {
Z z;
void f();
// …
};
和
template<class Z>
void A<Z>::f() {
Z z;
// …
}
尽管 namespace-scope 名称仍然可以进行相同的更改。
就是说,即使是委员会也已经 divided 遵守这一特定规则,因为更喜欢一个你在 base class 中看不到的名字而不是你在template-head.
C++ 标准规定来自非依赖基 类 的非限定名称优先于模板参数。这背后的原因是什么?
以下代码段来自 C++ 模板:
#include <iostream>
template <typename X>
class Base {
public:
int basefield;
using T = int;
};
class D1 : public Base<Base<void>> {
public:
void f() { basefield = 3; // works as normal
}
};
template <typename T>
class D2 : public Base<double> {
public:
void f() { basefield = 7; }
T strange; // what type am I ???
};
int main() {
D2<std::string> d;
d.strange = 100;
}
// what type am I ???
当在模板推导中查找不合格的名称时(如D2
),在模板参数列表之前考虑非依赖碱基。
在您的例子中,这意味着 class 模板 D2
的成员 strange
始终具有对应于 Base<double>::T
的类型 T
(这只不过是 int
).
您可以通过将 d.strange = 100;
更改为:
d.strange = "100"; //this will give error saying: invalid conversion from ‘const char*’ to ‘Base::T’ {aka ‘int’}
以上语句产生错误:
invalid conversion from ‘const char*’ to ‘Base::T’
{又名 ‘int’}
这确认 strange
具有类型 int
.
What is the reasoning behind this?
标准这么说的一个原因可能是因为当开始查找名称时,它会从遇到名称的位置向上(向上)。现在,在向上搜索名称时,首先遇到 non-dependent Base,因此名称被解析为属于 non-dependent Base(显然 Base 必须有一个名称相同的成员正在查找)。也就是说,因为在这种情况下 Base 独立于模板参数并且因为它在查找发生时首先出现(从名称声明的点到向上的方向),所以 non-dependent基础优先。
另一方面,在依赖 Base 的情况下,必须首先知道模板参数才能知道依赖 Base。也就是说,在这种情况下,Base 并不独立于模板参数。因此,当查找发生时(再次向上方向),即使在模板参数之前遇到依赖 Base,依赖 Base 在知道模板参数之前是未知的。所以在这种情况下,模板参数优先是有意义的。
这是我目前对标准如此规定的推理。
不合格查找大致等同于在每个包含范围内尝试 合格 查找并保持第一个命中。由于 D2<…>::T
可以找到 Base<double>::T
,因此在 class 的范围内查找成功;对于词法引入的模板参数,该查找自然先于 outside the class.
此首选项还可避免在
之间进行不合格的名称更改template<class T>
struct A : B {
Z z;
void f();
// …
};
和
template<class Z>
void A<Z>::f() {
Z z;
// …
}
尽管 namespace-scope 名称仍然可以进行相同的更改。
就是说,即使是委员会也已经 divided 遵守这一特定规则,因为更喜欢一个你在 base class 中看不到的名字而不是你在template-head.