3

http://en.cppreference.com/w/cpp/language/type_aliasによると、エイリアスはブロックレベルの宣言です。テンプレート エイリアスについて特別なことは何も言っていないので、テンプレート エイリアスもブロックレベルの宣言であることを理解しておいてください。

ただし、ブロック レベルでテンプレート エイリアスを使用することはできません。エラーはコンパイラによって異なります。g++ では意味のあるメッセージが表示され、テンプレートはブロック スコープでは許可されていませんが、clang は完全に不可解です。(例: http://coliru.stacked-crooked.com/a/0f0862dad6f3da61 )。

これまでの質問:

  • cppreference は、テンプレート エイリアスをブロック スコープで使用できないことを指定できませんか? (または、読書コースを受講する必要がありますか?)
  • コンパイラは、ブロック レベルでテンプレート エイリアスを拒否する点で正しいですか (私の特定のコーディング習慣にとって非常に興味深い機能です)。
  • 2 番目の答えが「はい」の場合、その理由は何でしょうか? コンパイラがこの純粋な構文糖衣を拒否するのはなぜですか?
4

2 に答える 2

6

エイリアス テンプレートは [temp.alias] です。

宣言が別名宣言であるテンプレート宣言 (第 7 節) は、識別子を別名テンプレートとして宣言します。エイリアス テンプレートは、型のファミリの名前です。エイリアス テンプレートの名前は template-name です。

そして、14.2 [temp] を見ると、

テンプレート宣言は、名前空間スコープまたはクラス スコープの宣言としてのみ表示できます。関数テンプレート宣言では、declarator-id の最後のコンポーネントは template-id であってはなりません。

したがって、cppreference は、ブロック スコープで宣言でき、コンパイラが正しいと言っています。ブロック宣言のリンクをクリックすると、宣言のリストが表示され、テンプレート宣言があり、そこに

クラス (構造体と共用体を含む)、メンバー クラスまたはメンバー列挙型、関数またはメンバー関数、名前空間スコープの静的データ メンバー、クラス スコープの変数または静的データ メンバーの宣言 (C++14以上)またはエイリアステンプレート (C++11以上) テンプレートの特殊化を定義することもできます。

テンプレートは名前空間スコープまたはクラススコープでのみ宣言できると標準が言う理由については、 James Kanzeの 回答が好きです

この問題はおそらく、テンプレートが実装された歴史的な方法に関連しています。初期の実装手法 (および今日でも使用されているもの) では、テンプレート内のすべてのシンボルに外部リンケージが必要です。(インスタンス化は、別のファイルで同等のコードを生成することによって行われます。) また、関数内で定義された名前にはリンケージがなく、それらが定義されたスコープの外で参照することはできません。

于 2015-09-24T18:15:33.760 に答える
1

コンパイラは正しく動作しています。

C++14 標準のセクション 14:

テンプレート宣言は、名前空間スコープまたはクラス スコープの宣言としてのみ表示できます。

于 2015-09-24T18:15:15.473 に答える