1. ホーム
  2. c++

[解決済み] C++11の'typedef'と'using'の違いは何ですか?

2022-03-16 08:21:04

質問内容

C++11では、以下のようなことができるようになりました。 using のように、型の別名を書くことができます。 typedef s:

typedef int MyInt;

は、私が理解するところでは、同等である。

using MyInt = int;

そして、この新しい構文は、"template typedef"を表現する方法を持つための努力から生まれたものです。

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

しかし、最初の2つのテンプレート以外の例で、他に規格の微妙な違いはあるのでしょうか?たとえば typedef はエイリアシングをquot;weak"方式で行います。つまり、新しい型を作るのではなく、新しい名前だけを作るのです(これらの名前間の変換は暗黙のうちに行われます)。

と同じなのでしょうか? using それとも新しい型を生成するのでしょうか?何か違いがあるのでしょうか?

解決方法は?

<サブ 以下の標準的なリファレンスは、すべて N4659:2017年3月コナ後のワーキングドラフト/C++17 DIS .


Typedef宣言は可能だが、alias宣言は不可能である。 (+) 初期化文として使用することができます。

<ブロッククオート

しかし、最初の2つのテンプレートでない例で、次のようになります。 他に規格の微妙な違いはあるのでしょうか?

  • 相違点 セマンティクス : ありません。
  • 相違点 許可されたコンテキストで : 一部 (++) .

(+) P2360R0 ( initステートメントを拡張し、エイリアス宣言を可能にした。 ) がCWGで承認されました C++23 では、typedef 宣言とエイリアス宣言の間のこの矛盾が取り除かれる予定である。
(++) の例の他に エイリアス テンプレート は、元の投稿ですでに言及されています。

同じセマンティクス

によって管理されています。 [dcl.typedef]/2 [抜粋 強調 私の]

<ブロッククオート

[dcl.typedef]/2 A 型定義名 によって導入することもできます。 エイリアス宣言 . は 識別子 に続いて using キーワードは 型定義名 と、オプションの 属性指定子-seq に続いて 識別子 は、その 型定義名 . このような 型定義名 によって導入されたのと同じ意味合いを持ちます。 typedef 指定子を使用します。 [...]

a 型定義名 によって紹介されました。 エイリアス宣言 があります。 同じセマンティクス によって導入されたかのように 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;
}

一方 エイリアス宣言 ではない アン イニシャルステートメント であり、したがって はいけません。 初期化ステートメントを許可するコンテキストで使用されます。

// 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