gpt4 book ai didi

c++ - 带有模板基类的 "definition of a static data member is in the scope of its class"规范规则

转载 作者:行者123 更新时间:2023-12-03 10:04:24 25 4
gpt4 key购买 nike

C++ 规范(例如 C++17 [class.static] §2 )说:

The definition of a static data member is in the scope of its class.


举个例子(取自 C++14 spec ):
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
由于某些未知原因,规范中的确切措辞和示例多年来发生了变化, C++11C++14有一个与上面非常相似的例子, C++17C++20首选从静态数据成员初始化的示例。 C++20措辞也更加简洁。但似乎这条规则并没有实际的变化。

看来这条规则 doesn't work well对于模板类的继承:
template<int VALUE>
struct base {
static int foo() { return VALUE; }
static constexpr int z = -1;
};

template<int VALUE>
struct foobar: base<VALUE> {
static int x1;
static int x2;
static int y1;
static int y2;
};

int foo() { return 42; }

int z = 999;

template<int VALUE>
int foobar<VALUE>::x1 = foobar::foo();

template<int VALUE>
int foobar<VALUE>::x2 = foo();

template<int VALUE>
int foobar<VALUE>::y1 = foobar::z;

template<int VALUE>
int foobar<VALUE>::y2 = z;

int main() {
std::cout << foobar<10>::x1 << ' ' << foobar<10>::x2 << ' '
<< foobar<10>::y1 << ' ' << foobar<10>::y2;
}
输出:
10 42 -1 999
GCC 10.2 和 Clang 5.0.0 都同意上述(令人惊讶的?)输出。
它是正确的输出,还是两个编译器中的错误?
预期的输出,期望调用 foo() ,在静态成员初始化的上下文中,将表现为调用 foobar::foo()等,应该是:
10 10 -1 -1

注意: inheritance 的行为以及 a template class without inheritancea template base with a non-template derived ,一切似乎都正常工作。

最佳答案

GCC 和 Clang 都是正确的。
特别是来自 [temp.dep]/3 [ 重点矿]:

In the definition of a class or class template, the scope of adependent base class is not examined during unqualified name lookupeither at the point of definition of the class template or member orduring an instantiation of the class template or member. [ Example:

typedef double A;
template<class T> class B {
typedef int A;
};
template<class T> struct X : B<T> {
A a; // a has type double
};

The type name A in the definition of X<T> binds to the typedefname defined in the global namespace scope, not to the typedef namedefined in the base class B<T>.  — end example ] [...]


在定义中,静态数据成员 x1y1派生类模板的 foobar :
template<int VALUE>
int foobar<VALUE>::x1 = foobar::foo();

template<int VALUE>
int foobar<VALUE>::y1 = foobar::z;
您正在使用注入(inject)的类名 ( [temp.local]/3 ) 来访问从属名称 ( [temp.res]/9 ) fooz来自 base类模板,而静态数据成员定义中使用的非限定名称 x2y2不会检查依赖基类的范围。

请注意,我们可能会引入依赖 base 的名称。类进入派生类的范围,重新定义 foobar作为
template<int VALUE>
struct foobar: base<VALUE> {
using base<VALUE>::foo;
using base<VALUE>::z;
static int x1;
static int x2;
static int y1;
static int y2;
};
在这种情况下,您的程序的输出将是
10 10 -1 -1

关于c++ - 带有模板基类的 "definition of a static data member is in the scope of its class"规范规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65597681/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com