我知道在 C++11 中我们现在可以using用来写类型别名,比如typedefs:
using
typedef
typedef int MyInt;
据我了解,相当于:
using MyInt = int;
新语法源于努力表达“模板类型定义”:
template< class T > using MyType = AnotherType< T, MyAllocatorType >;
但是,对于前两个非模板示例,标准中是否还有其他细微差别?例如,typedefs 以“弱”的方式进行混叠。也就是说,它不会创建新类型,而只会创建一个新名称(这些名称之间的转换是隐含的)。
它是相同的using还是生成一个新的类型?有什么不同吗?
以下所有标准参考均指 N4659:2017 年 3 月 Kona 后工作草案/C++17 DIS。
但是,对于前两个非模板示例,标准中是否还有其他细微差别?
(+) P2360R0 ( Extend init-statement to allow alias-declaration )已被 CWG 批准,从 C23 开始,typedef 声明和别名声明之间的这种不一致将被删除。 () 除了 别名模板 的例子,在原帖中已经提到过。
由[dcl.typedef]/2 [摘录, 强调 我的]管理
[dcl.typedef]/2 typedef -name 也可以通过 alias- declaration 引入。关键字后面的标识符 成为usingtypedef -name ,标识符后面的可选 属性说明 符 序列属于该 typedef-name 。 这样的 typedef-name 具有相同的语义,就好像它是由说明typedef符引入的一样。[…]
由 别名声明 引入的 typedef-name 与由声明引入的语义 相同* 。 __ *typedef
然而,这并不 意味着 这两种变体对于它们可能被使用 的上下文具有相同的限制。 事实上,尽管是一个极端情况, typedef 声明 是一个 init 语句 ,因此可以在允许初始化语句的上下文中使用
// C++11 (C++03) (init. statement in for loop iteration statements). for (typedef int Foo; Foo{} != 0;) // ^^^^^^^^^^^^^^^ init-statement { } // C++17 (if and switch initialization statements). if (typedef int Foo; true) // ^^^^^^^^^^^^^^^ init-statement { (void)Foo{}; } switch (typedef int Foo; 0) // ^^^^^^^^^^^^^^^ init-statement { case 0: (void)Foo{}; } // C++20 (range-based for loop initialization statements). std::vector<int> v{1, 2, 3}; for (typedef int Foo; Foo f : v) // ^^^^^^^^^^^^^^^ init-statement { (void)f; } for (typedef struct { int x; int y;} P; auto [x, y] : {P{1, 1}, {1, 2}, {3, 5}}) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ init-statement { (void)x; (void)y; }
而 别名声明 不是 init-statement ,因此 不能* 在允许初始化语句的上下文中 使用 __ *
// 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