Take the following standard passage:
以下列标准段落为例:
[C++11: 5.3.3/6]:
The result ofsizeof
andsizeof...
is a constant of typestd::size_t
. [ Note:std::size_t
is defined in the standard header<cstddef>
(18.2). —end note ][C+ 11: 5.3.3/6]: sizeof和sizeof…是std: size_t类型的常数。[注:std::size_t定义在标准头
(18.2)中。端注)
Now:
现在:
[C++11: 18.2/6]:
The typesize_t
is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object.[c++ 11: 18.2/6]: size_t是一个实现定义的无符号整数类型,其大小足以包含任何对象的字节大小。
Granted, the passage doesn't require that size_t
is a type alias defined with typedef
, but since it's explicitly stated to be made available by the standard header <cstddef>
, I think we can take as read that failing to include <cstddef>
should remove any guarantee that size_t
shall be available to a program.
当然,不需要通过size_t使用typedef定义一个类型别名,但因为它是显式声明的可用标准头< cstddef >,我认为我们可以为已读,未包括< cstddef >应该删除任何保证size_t应当提供给一个程序。
However, according to that first quote, we can regardless obtain an expression of type std::size_t
.
但是,根据第一个引用,我们可以不考虑获得std::size_t类型的表达式。
We can actually demonstrate both of these facts:
我们可以证明这两个事实
int main()
{
typedef decltype(sizeof(0)) my_size_t;
my_size_t x = 0; // OK
std::size_t y = 1; // error: 'size_t' is not a member of 'std'
}
std::size_t
is not visible to the program, but sizeof(0)
still gives us one? Really?
size_t在程序中是不可见的,但是sizeof(0)仍然给我们一个?真的吗?
Is it therefore not correct to say that 5.3.3/6
is flawed, and that it actually has "the same type as whatever std::size_t
resolves to", but not std::size_t
itself?
因此,如果说5.3.3/6是有缺陷的,并且它实际上有“与std相同的类型:size_t解析为”,而不是std::size_t本身,这是不正确的吗?
Sure, the two are one and the same if std::size_t
is a type alias but, again, nowhere is this actually required.
当然,如果std::size_t是一个类型别名,这两者是一个,也是一样的,但是,同样地,没有任何地方需要它。
5 个解决方案
#1
45
Do not confuse the map for the territory.
不要把地图与领土混淆。
Types can be named by typenames. These typenames can be built-in, they can be user-defined types, or they could even be template
parameters and refer to multiple different types depending on the instantiation.
类型可以由typenames命名。这些typenames可以是内置的,也可以是用户定义的类型,或者甚至可以是模板参数,根据实例化引用多个不同的类型。
But the names are not the types. Clearly standard does not mandate that all types have names -- the classic struct {}
is a type without a name.
但是名字不是类型。显然,标准并不要求所有类型都有名称——典型的struct{}是没有名称的类型。
std::size_t
is a typename. It names the type that sizeof(expression)
returns.
std::size_t typename。它为sizeof(表达式)返回的类型命名。
The compiler could have a canonical name for the type -- __size_t
would be one way for it to have a unique built-in canonical typename.
编译器可以有一个类型的规范名称——__size_t是它具有唯一的内置规范typename的一种方式。
The standard guarantees in that clause that whatever the type of sizeof(expression)
is, once you #include <cstddef>
, the name std::size_t
now refers to that type.
该子句中的标准保证,无论sizeof(表达式)的类型是什么,一旦您#包含
In the standard, they refer to types by names. They do not say "the type that this typename refers to", but simply say "the type $NAME$". The compiler could decide that int
is another name for __int_32_fast
if it wanted to, and the standard would have no objection either.
在标准中,它们通过名称引用类型。他们不会说“这个typename所指的类型”,而是简单地说“类型$NAME$”。如果需要,编译器可以决定int是__int_32_fast的另一个名称,并且标准也不会反对。
This same thing happens with std::nullptr_t
and std::initializer_list<Ts>
and std::type_info
: use of variables of those types does not always require that the header that provides you with a name for those types be included in your program.
std::nullptr_t和std::initializer_list
The traditional C/C++ built-in types all had canonical names that did not require a header. The downside is that this breaks existing code, as new typenames in the global scope collide with other identifiers.
传统的C/ c++内置类型都有不需要标头的规范名称。缺点是这会破坏现有的代码,因为全局范围中的新typenames会与其他标识符发生冲突。
By having "nameless types", where you can get a name for them via including a header file, we avoid that problem.
通过拥有“无名类型”,您可以通过包含头文件获得它们的名称,我们避免了这个问题。
#2
51
The standard just mandates that the type of sizeof(expr)
is the same type as std::size_t
. There is no mandate that using sizeof(expr)
makes the name std::size_t
available and since std::size_t
just names one of the the built-in integral types there isn't really a problem.
该标准只要求sizeof(expr)的类型与std::size_t的类型相同。使用sizeof(expr)并没有强制要求std: size_t这个名字是可用的,而且因为std::size_t只命名了一个内置的整型类型,所以没有问题。
#3
5
As I understand it, this standard passage requires the following expression:
根据我的理解,这一标准段落需要以下表达:
typeid(sizeof(0)) == typeid(std::size_t)
will always yield true
. If you use the actual identifier std::size_t
, ::size_t
or any other alias/typedef will be irrelevant as long as the identity of the type, as per std::typeinfo::operator==()
, is preserved.
总是会产生真实的。如果您使用实际的标识符std::size_t,::size_t或任何其他别名/typedef将与类型的标识无关,就像std::typeinfo::operator==(),保存。
The same type identity issue appears in other places of the language. For example, in my 64-bit machine the following code fails to compile because of function redefinition:
相同的类型标识问题出现在语言的其他地方。例如,在我的64位机中,由于重新定义函数,以下代码无法编译:
#include <cstddef>
void foo(std::size_t x)
{}
void foo(unsigned long x)
{}
#4
5
Yes.
是的。
The type yielded by sizeof
is some unsigned integer type; the implementation defines which one it is.
sizeof得到的类型是某个无符号整数类型;实现定义了它是哪个。
For example, on some particular implementation, the type of a sizeof
expression might be unsigned long
.
例如,在某些特定的实现中,sizeof表达式的类型可能是无符号长。
std::size_t
, if it's a typedef
, is nothing more than an alternative name for unsigned long
. So these two statements:
如果是typedef,那么size_t只不过是unsigned long的替代名称。这两个语句:
The type of
sizeof ...
is a constant of typeunsigned long
尺寸的类型…一个常量类型是unsigned long吗?
and
和
The type of
sizeof ...
is a constant of typestd::size_t
尺寸的类型…是std类型的常量::size_t ?
are saying exactly the same thing for that implementation. The type unsigned long
and the type std::size_t
are the same type. The difference is that the latter is accurate for all (conforming) implementations, where std::size_t
might be an alias for, say, unsigned int
or some other unsigned type.
对实现来说是完全一样的。类型unsigned long和类型std::size_t是相同的类型。不同的是,后者对于所有(符合要求的)实现都是准确的,其中std::size_t可能是无符号int或其他无符号类型的别名。
As far as the compiler is concerned, sizeof
yields a result of type unsigned long
; the compiler (as opposed to the runtime library) needn't have any knowledge of the name size_t
.
就编译器而言,sizeof产生的结果是无符号长类型;编译器(与运行时库相反)不需要知道size_t这个名称。
This all assumes that std::size_t
(or just size_t
if you're talking about C) is a typedef. That's not spelled out in either the C or the C++ standard. Nevertheless, an implementation can straightforwardly conform to the requirements of the standard by making size_t
a typedef. I don't believe there's any other portable way to satisfy those requirements. (It can't be a macro or an implementation-defined keyword because that would infringe on the user's name space, and a macro wouldn't be scoped within the std
namespace.) A compiler could make size_t
some implementation-specific construct other than a typedef, but since a typedef works perfectly well, there's no point in doing so. It would be nice, IMHO, if the standard stated that size_t
is a typedef.
所有这些都假设std::size_t(或者只是size_t,如果你说的是C)是一个typedef。这在C和c++标准中都没有说明。然而,通过将size_t设置为typedef,实现可以直接符合标准的要求。我不相信还有其他的便携式方法可以满足这些要求。(它不能是一个宏或一个实现定义的关键字,因为这会侵犯用户的名称空间,而且一个宏不会在std名称空间中限定范围。)编译器可以使size_t某些特定于实现的构造,而不是typedef,但是由于typedef的工作非常好,所以没有必要这样做。如果标准声明size_t是一个typedef,那就太好了。
(An irrelevant aside: The real problem is that the standard refers to the result as a "constant". In ISO C, a "constant" is a token, such as an integer literal. C++, as far as I know, doesn't define the noun "constant", but it does refer to the ISO C definition of the term. sizeof ...
is a constant expression; it's not a constant. Calling the result a "constant value" would have been reasonable.)
(顺便说一句:真正的问题是,标准将结果作为“常数”。在ISO C中,“常量”是一个标记,如整数文字。就我所知,c++并没有定义名词“常数”,但它确实是指这个词的ISO C定义。sizeof……是一个常量表达式;这不是一个常数。将结果称为“常量值”是合理的。
#5
2
It is the same type but you have to include that header to use it.
它是相同的类型,但是您必须包含该头才能使用它。
#1
45
Do not confuse the map for the territory.
不要把地图与领土混淆。
Types can be named by typenames. These typenames can be built-in, they can be user-defined types, or they could even be template
parameters and refer to multiple different types depending on the instantiation.
类型可以由typenames命名。这些typenames可以是内置的,也可以是用户定义的类型,或者甚至可以是模板参数,根据实例化引用多个不同的类型。
But the names are not the types. Clearly standard does not mandate that all types have names -- the classic struct {}
is a type without a name.
但是名字不是类型。显然,标准并不要求所有类型都有名称——典型的struct{}是没有名称的类型。
std::size_t
is a typename. It names the type that sizeof(expression)
returns.
std::size_t typename。它为sizeof(表达式)返回的类型命名。
The compiler could have a canonical name for the type -- __size_t
would be one way for it to have a unique built-in canonical typename.
编译器可以有一个类型的规范名称——__size_t是它具有唯一的内置规范typename的一种方式。
The standard guarantees in that clause that whatever the type of sizeof(expression)
is, once you #include <cstddef>
, the name std::size_t
now refers to that type.
该子句中的标准保证,无论sizeof(表达式)的类型是什么,一旦您#包含
In the standard, they refer to types by names. They do not say "the type that this typename refers to", but simply say "the type $NAME$". The compiler could decide that int
is another name for __int_32_fast
if it wanted to, and the standard would have no objection either.
在标准中,它们通过名称引用类型。他们不会说“这个typename所指的类型”,而是简单地说“类型$NAME$”。如果需要,编译器可以决定int是__int_32_fast的另一个名称,并且标准也不会反对。
This same thing happens with std::nullptr_t
and std::initializer_list<Ts>
and std::type_info
: use of variables of those types does not always require that the header that provides you with a name for those types be included in your program.
std::nullptr_t和std::initializer_list
The traditional C/C++ built-in types all had canonical names that did not require a header. The downside is that this breaks existing code, as new typenames in the global scope collide with other identifiers.
传统的C/ c++内置类型都有不需要标头的规范名称。缺点是这会破坏现有的代码,因为全局范围中的新typenames会与其他标识符发生冲突。
By having "nameless types", where you can get a name for them via including a header file, we avoid that problem.
通过拥有“无名类型”,您可以通过包含头文件获得它们的名称,我们避免了这个问题。
#2
51
The standard just mandates that the type of sizeof(expr)
is the same type as std::size_t
. There is no mandate that using sizeof(expr)
makes the name std::size_t
available and since std::size_t
just names one of the the built-in integral types there isn't really a problem.
该标准只要求sizeof(expr)的类型与std::size_t的类型相同。使用sizeof(expr)并没有强制要求std: size_t这个名字是可用的,而且因为std::size_t只命名了一个内置的整型类型,所以没有问题。
#3
5
As I understand it, this standard passage requires the following expression:
根据我的理解,这一标准段落需要以下表达:
typeid(sizeof(0)) == typeid(std::size_t)
will always yield true
. If you use the actual identifier std::size_t
, ::size_t
or any other alias/typedef will be irrelevant as long as the identity of the type, as per std::typeinfo::operator==()
, is preserved.
总是会产生真实的。如果您使用实际的标识符std::size_t,::size_t或任何其他别名/typedef将与类型的标识无关,就像std::typeinfo::operator==(),保存。
The same type identity issue appears in other places of the language. For example, in my 64-bit machine the following code fails to compile because of function redefinition:
相同的类型标识问题出现在语言的其他地方。例如,在我的64位机中,由于重新定义函数,以下代码无法编译:
#include <cstddef>
void foo(std::size_t x)
{}
void foo(unsigned long x)
{}
#4
5
Yes.
是的。
The type yielded by sizeof
is some unsigned integer type; the implementation defines which one it is.
sizeof得到的类型是某个无符号整数类型;实现定义了它是哪个。
For example, on some particular implementation, the type of a sizeof
expression might be unsigned long
.
例如,在某些特定的实现中,sizeof表达式的类型可能是无符号长。
std::size_t
, if it's a typedef
, is nothing more than an alternative name for unsigned long
. So these two statements:
如果是typedef,那么size_t只不过是unsigned long的替代名称。这两个语句:
The type of
sizeof ...
is a constant of typeunsigned long
尺寸的类型…一个常量类型是unsigned long吗?
and
和
The type of
sizeof ...
is a constant of typestd::size_t
尺寸的类型…是std类型的常量::size_t ?
are saying exactly the same thing for that implementation. The type unsigned long
and the type std::size_t
are the same type. The difference is that the latter is accurate for all (conforming) implementations, where std::size_t
might be an alias for, say, unsigned int
or some other unsigned type.
对实现来说是完全一样的。类型unsigned long和类型std::size_t是相同的类型。不同的是,后者对于所有(符合要求的)实现都是准确的,其中std::size_t可能是无符号int或其他无符号类型的别名。
As far as the compiler is concerned, sizeof
yields a result of type unsigned long
; the compiler (as opposed to the runtime library) needn't have any knowledge of the name size_t
.
就编译器而言,sizeof产生的结果是无符号长类型;编译器(与运行时库相反)不需要知道size_t这个名称。
This all assumes that std::size_t
(or just size_t
if you're talking about C) is a typedef. That's not spelled out in either the C or the C++ standard. Nevertheless, an implementation can straightforwardly conform to the requirements of the standard by making size_t
a typedef. I don't believe there's any other portable way to satisfy those requirements. (It can't be a macro or an implementation-defined keyword because that would infringe on the user's name space, and a macro wouldn't be scoped within the std
namespace.) A compiler could make size_t
some implementation-specific construct other than a typedef, but since a typedef works perfectly well, there's no point in doing so. It would be nice, IMHO, if the standard stated that size_t
is a typedef.
所有这些都假设std::size_t(或者只是size_t,如果你说的是C)是一个typedef。这在C和c++标准中都没有说明。然而,通过将size_t设置为typedef,实现可以直接符合标准的要求。我不相信还有其他的便携式方法可以满足这些要求。(它不能是一个宏或一个实现定义的关键字,因为这会侵犯用户的名称空间,而且一个宏不会在std名称空间中限定范围。)编译器可以使size_t某些特定于实现的构造,而不是typedef,但是由于typedef的工作非常好,所以没有必要这样做。如果标准声明size_t是一个typedef,那就太好了。
(An irrelevant aside: The real problem is that the standard refers to the result as a "constant". In ISO C, a "constant" is a token, such as an integer literal. C++, as far as I know, doesn't define the noun "constant", but it does refer to the ISO C definition of the term. sizeof ...
is a constant expression; it's not a constant. Calling the result a "constant value" would have been reasonable.)
(顺便说一句:真正的问题是,标准将结果作为“常数”。在ISO C中,“常量”是一个标记,如整数文字。就我所知,c++并没有定义名词“常数”,但它确实是指这个词的ISO C定义。sizeof……是一个常量表达式;这不是一个常数。将结果称为“常量值”是合理的。
#5
2
It is the same type but you have to include that header to use it.
它是相同的类型,但是您必须包含该头才能使用它。