问题描述
我知道在 C++11 中我们现在可以使用 using
来编写类型别名,比如 typedef
s:
I know that in C++11 we can now use using
to write type alias, like typedef
s:
typedef int MyInt;
据我所知,相当于:
using MyInt = int;
这种新的语法是为了有一种表达模板类型定义"的方法而产生的:
And that new syntax emerged from the effort to have a way to express "template typedef":
template< class T > using MyType = AnotherType< T, MyAllocatorType >;
但是,对于前两个非模板示例,标准中是否还有其他细微差别?例如,typedef
s 在弱"代码中做别名处理.道路.也就是说,它不会创建新类型,而只会创建新名称(这些名称之间的转换是隐式的).
But, with the first two non-template examples, are there any other subtle differences in the standard? For example, typedef
s do aliasing in a "weak" way. That is it does not create a new type but only a new name (conversions are implicit between those names).
和using
一样还是生成新的类型?有什么不同吗?
Is it the same with using
or does it generate a new type? Are there any differences?
推荐答案
以下所有标准参考参考 N4659:2017 年 3 月 Kona 后工作草案/C++17 DIS.
但是,对于前两个非模板示例,标准中还有其他细微差别吗?
But, with the first two non-template examples, are there any other subtle differences in the standard?
- 差异语义:无.
- 差异在允许的上下文中:一些(1).
- Differences in semantics: none.
- Differences in allowed contexts: some(1).
(1) 除了别名模板的例子,在原帖中已经提到.
(1) In addition to the examples of alias templates, which has already been mentioned in the original post.
受 [dcl.typedef]/2 管辖[摘录,强调我的]
As governed by [dcl.typedef]/2 [extract, emphasis mine]
[dcl.typedef]/2typedef-name也可以通过介绍别名声明.using
关键字后面的 identifier 变成了typedef-name 和 identifier 后面的可选 attribute-specifier-seq 属于那个 typedef-name.这样的typedef-name 与由 typedef
说明符引入的语义相同. [...]
[dcl.typedef]/2 A typedef-name can also be introduced by an alias-declaration. The identifier following the
using
keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. Such a typedef-name has the same semantics as if it were introduced by thetypedef
specifier. [...]
由别名声明引入的typedef-name与typedef<引入具有相同的语义/code> 声明.
a typedef-name introduced by an alias-declaration has the same semantics as if it were introduced by the typedef
declaration.
然而,这并不暗示这两种变体在使用环境方面具有相同的限制.事实上,尽管是极端情况,typedef 声明 是一个 init-statement 因此可以在允许初始化语句的上下文中使用
However, this does not imply that the two variations have the same restrictions with regard to the contexts in which they may be used. And indeed, albeit a corner case, a typedef declaration is an init-statement and may thus be used in contexts which allow initialization statements
// C++11 (C++03) (init. statement in for loop iteration statements).
for(typedef int Foo; Foo{} != 0;) {}
// C++17 (if and switch initialization statements).
if (typedef int Foo; true) { (void)Foo{}; }
// ^^^^^^^^^^^^^^^ init-statement
switch(typedef int Foo; 0) { case 0: (void)Foo{}; }
// ^^^^^^^^^^^^^^^ init-statement
// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for(typedef int Foo; Foo f : v) { (void)f; }
// ^^^^^^^^^^^^^^^ init-statement
for(typedef struct { int x; int y;} P;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ init-statement
auto [x, y] : {P{1, 1}, {1, 2}, {3, 5}}) { (void)x; (void)y; }
而 别名声明不是一个init-statement,因此不能在允许初始化语句的上下文中使用
whereas an alias-declaration is not an init-statement, and thus may not be used in contexts which allows initialization statements
// C++ 11.
for(using Foo = int; Foo{} != 0;) {}
// ^^^^^^^^^^^^^^^ error: expected expression
// C++17 (initialization expressions in switch and if statements).
if (using Foo = int; true) { (void)Foo{}; }
// ^^^^^^^^^^^^^^^ error: expected expression
switch(using Foo = int; 0) { case 0: (void)Foo{}; }
// ^^^^^^^^^^^^^^^ error: expected expression
// C++20 (range-based for loop initialization statements).
std::vector<int> v{1, 2, 3};
for(using Foo = int; Foo f : v) { (void)f; }
// ^^^^^^^^^^^^^^^ error: expected expression
这篇关于C++11 中的“typedef"和“using"有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!