以下所有标准参考资料均参考N4659: 2017年3月后kona工作草案/ c++ 17 DIS。
Typedef声明可以用作初始化语句,而别名声明不能(+)
但是,对于前两个非模板示例,是
标准上还有其他细微的差别吗?
语义上的差异:无。
允许上下文中的差异:一些(++)。
(+) P2360R0(扩展初始化语句以允许别名声明)已经被CWG批准,从c++ 23开始,类型定义声明和别名声明之间的不一致将被消除。
(++)除了别名模板的例子,这在原来的帖子中已经提到过。
相同的语义
由[dcl.]管理。/2[提取,强调矿山]
(dcl。typedef) / 2
类型名
还可以介绍一个
alias-declaration。
using关键字后面的标识符变成a
typef -name和标识符后面的可选属性说明符-seq都属于该typef -name。这样一个
typepedef -name具有与typedef说明符引入的相同的语义。[…]
由别名声明引入的typepedef -name与由typedef声明引入的typef -name具有相同的语义。
允许上下文的细微差别
然而,这并不意味着这两种变体在使用上下文方面有相同的限制。实际上,尽管是极端情况,typedef声明是一个初始化语句,因此可以在允许初始化语句的上下文中使用
// 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;
}
而别名声明不是初始化语句,因此不能在允许初始化语句的上下文中使用
// 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