[英]Is it legal to redefine a type name?
Chapter 7.4.1 of the book C++ Primer says the following: C++ Primer 一书的第 7.4.1 章说:
Ordinarily, an inner scope can redefine a name from an outer scope even if that name has already been used in the inner scope.
通常,内部 scope 可以从外部 scope 重新定义名称,即使该名称已在内部 scope 中使用。 However, in a class, if a member uses a name from an outer scope and that name is a type, then the class may not subsequently redefine that name
但是,在 class 中,如果成员使用来自外部 scope 的名称并且该名称是类型,则 class 随后可能不会重新定义该名称
The word subsequently makes me think that it is only an error to redefine a type name after it has been used in the class.这个词随后让我认为在 class 中使用类型名称后重新定义它只是一个错误。 However, two paragraphs later it says:
然而,两段后它说:
Although it is an error to redefine a type name, compilers are not required to diagnose this error.
尽管重新定义类型名称是错误的,但编译器不需要诊断此错误。
Does this mean that it is an error to redefine a type name even before it has been used in a class?这是否意味着在 class 中使用类型名称之前重新定义它是错误的?
It seems that the quote refers to the following case似乎引用是指以下情况
typedef int T;
struct A
{
T a[10];
typedef double T;
};
That is the code is ill-formed due to the redeclaration of the name T
within the class definition that was already used in the declaration of the data member a
.也就是说,由于在数据成员
a
的声明中已使用的 class 定义中重新声明了名称T
,因此代码格式错误。
If you will just write如果你只写
typedef int T;
struct A
{
int a[10];
typedef double T;
};
then this code is correct.那么这段代码是正确的。 The name
T
is not used as a type specifier in declarations of members of the class A.在 class A 的成员声明中,名称
T
不用作类型说明符。
The OP writes in the comment section: OP在评论部分写道:
... My question is wether [ sic ] it is legal to redefine a type name before it has been used in a class.
...我的问题是 [原文如此] 在 class 中使用之前重新定义类型名称是否合法。
The answer is yes.答案是肯定的。 It is legal to define a type name in a class that shadows a type name in an enclosing scope.
在 class 中定义类型名称是合法的,它会在封闭的 scope 中隐藏类型名称。 What is not allowed is the following:
不允许的情况如下:
T
(though it need not be a type), is used inside a class, and name lookup finds some declaration D
, andT
(尽管它不必是类型),名称查找会找到一些声明D
,并且T
, and T
的成员,并且T
, it now finds the new member declaration instead of D
.T
,它现在会找到新的成员声明而不是D
。 Let's go over a few examples to clarify the issue.让我们通过几个例子来说明问题。
using T = X;
class C {
using T = Y;
T x;
};
The above example is legal because when the compiler sees T x;
上面的例子是合法的,因为当编译器看到
T x;
, it has already seen using T = Y;
, 它已经
using T = Y;
, so T
can only resolve to Y
. ,所以
T
只能解析为Y
。 There are no subsequent declarations inside the class that can change the meaning later. class 内部没有后续可以更改含义的声明。
using T = X;
class C {
T x;
using T = Y;
};
The above example is illegal.上面的例子是非法的。 The compiler at first looks up
T
and finds the enclosing definition of T
as X
, since C::T
hasn't been declared yet.编译器首先查找
T
并找到T
的封闭定义为X
,因为C::T
尚未声明。 But after C::T
has been declared, it implies that if T x;
但是在声明了
C::T
之后,意味着如果T x;
were to be reinterpreted, then T
would now refer to C::T
instead, since the class scope takes precedence over the enclosing scope. were to be reinterpreted, then
T
would now refer to C::T
instead, since the class scope takes precedence over the enclosing scope.
using T = ::X;
class C {
T x;
using T = ::X;
};
The above example is illegal.上面的例子是非法的。 The fact that both declarations of
T
make it refer to the same type is not relevant. T
的两个声明都使其引用相同类型的事实无关紧要。 The violation occurs because T x;
违规发生是因为
T x;
would find a different declaration of T
after the class is completely defined.在完全定义 class 之后会发现
T
的不同声明。
using T = X;
class C {
::T x;
using T = Y;
};
The above example is legal.上面的例子是合法的。 The declaration
using T = Y;
using T = Y;
does not change the meaning of ::T
, because ::T
will always refer to the global declaration even though C::T
is there.不会改变
::T
的含义,因为::T
将始终引用全局声明,即使C::T
存在。
using T = X;
class C {
void foo() { T x; }
using T = Y;
};
The above example is legal.上面的例子是合法的。 The body of
foo
is a complete-class context , which implies that name lookup for T
is not done until after the entire class has been seen. foo
的主体是一个完整的类 context ,这意味着直到看到整个 class 之后才完成对T
的名称查找。 Put another way, the declaration using T = Y;
换句话说,声明
using T = Y;
in a sense always "precedes" the body of foo
so this is similar to the first example.在某种意义上总是“先于”
foo
的主体,所以这类似于第一个示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.