以下のすべての標準参照は、N4659:2017年3月のコナ後の作業ドラフト/ C ++17DISを参照しています。
Typedef宣言は可能ですが、エイリアス宣言は初期化ステートメントとして使用できません(+) 。
しかし、最初の2つの非テンプレートの例では、標準に他の微妙な違いはありますか?
- セマンティクスの違い:なし。
- 許可されるコンテキストの違い:いくつか(++)。
(+)P2360R0(エイリアス宣言を許可するようにinitステートメントを拡張する)はCWGによって承認されており、C ++ 23以降、typedef宣言とエイリアス宣言の間のこの不整合は削除されます。
(++)元の投稿ですでに言及されているエイリアステンプレート
の例に加えて。
同じセマンティクス
[dcl.typedef] / 2 [抽出、強調鉱山]によって管理されます
[dcl.typedef] / 2 typedef-nameは、 alias-declarationによって導入する
こともできます
。キーワードに続く識別子はtypedef-nameになり、
識別子に続くオプションのattribute - specifier-seqはそのtypedef-nameに関連します。このような
typedef-nameは、指定者によって導入された場合と同じセマンティクスを持ちます。[...]using
typedef
alias-declarationによって導入されたtypedef-nameは、宣言によって導入された場合と同じセマンティクスを持ちます。typedef
許可されたコンテキストの微妙な違い
ただし、これは、2つのバリエーションが使用されるコンテキストに関して同じ制限があることを意味するものではありません。実際、コーナーケースではありますが、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;
}
一方、alias-declarationは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