小编典典

C ++ 11中的'typedef'和'using'有什么区别?

all

我知道在 C++11 中我们现在可以using用来写类型别名,比如typedefs:

typedef int MyInt;

据我了解,相当于:

using MyInt = int;

新语法源于努力表达“模板类型定义”:

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

但是,对于前两个非模板示例,标准中是否还有其他细微差别?例如,typedefs
以“弱”的方式进行混叠。也就是说,它不会创建新类型,而只会创建一个新名称(这些名称之间的转换是隐含的)。

它是相同的using还是生成一个新的类型?有什么不同吗?


阅读 133

收藏
2022-02-28

共1个答案

小编典典

以下所有标准参考均指 N4659:2017 年 3 月 Kona 后工作草案/C++17 DIS


Typedef 声明可以用作初始化语句,而别名声明不能(+)用作初始化语句

但是,对于前两个非模板示例,标准中是否还有其他细微差别?

  • 语义 差异:无。
  • 允许的上下文中的 差异:一些(++)。

(+) 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
2022-02-28