4

g++ 3.4.5 は次のコードを受け入れます。

template <typename T> struct A
{
    static const char* const str;
};

struct B {};

typedef A<B> C;

template<> const char* const C::str = "B";
// Equivalent to following?
// template<> const char* const A<B>::str = "B";

しかし、それが実際に合法的な C++03 であるかどうかはわかりません。特に、

[14.7p3] クラス テンプレート、クラス テンプレートのメンバー、またはクラス メンバー テンプレートの明示的な特殊化宣言では、明示的に特殊化されるクラスの名前は template-id になります。

この要件は、この例の最後で非 typedef バージョンを使用する必要があることを示していますか? それとも私は何かを誤解しましたか?

編集: さらなる証拠:欠陥レポート 403は、型 (そのコンテキストでは、関数呼び出し式の引数の型) を template-id と言うのは正しくないことを示唆します。 1。標準のその後のドラフトでは、3.4.2の「 template-id 」の代わりに「クラス テンプレートの特殊化」が使用されています。

A<B>これは、 と が同じ型をC表している (そして、同一またはほぼ同一の意味的意味を持っている)が、テンプレート ID でありA<B>テンプレートIDCはないという引数をサポートします。それらのトークンの意味。

4

2 に答える 2

4

これは厳密には形式が正しくないと思います (少なくとも C++ '03 によると)。

私の論理は、typedef(7.1.3/1)ですが:

... したがって、別のタイプの同義語です。

標準には、 a が必要な場所で typedef を使用することを明示的に許可する単語がまだありますclass-name(7.1.3/4):

クラスに名前を付ける typedef-name はクラス名です

にそのような言葉はありませんtemplate-id

于 2010-12-16T19:46:19.063 に答える
0

そこには明示的な特殊化は当てはまらないと思います。テンプレートなしで同様のコードを書くことができます:

struct A
{
    static const char* const str;
};

typedef A C;

const char* const C::str = "B";

A の代わりに C を使用しても、このコードは完全に正しいです。C は単なるエイリアスです。

C++ コードがどのように処理されるか想像してみてください。Typedef は、テンプレートのインスタンス化プロセスが開始される前に、コンパイラによって明らかに展開されます。すべてのコメントがマクロの前に展開されるのと同じです。実際の C++ 解析が開始される前に、すべてのマクロがプリプロセッサによって展開されるためです。これにより、すべてが簡素化されます。

C++03標準については、それを見てください

7.1.3/1 typedef 指定子で宣言された名前は typedef 名になります。その宣言の範囲内では、typedef-name は 構文的にキーワードと同等であり、8 節で説明されている方法で識別子に関連付けられた型に名前を付けます。したがって、typedef-name は別の型の同義語です。typedef-name は、クラス宣言 (9.1) または enum 宣言のように新しい型を導入しません。

この段落は、コード内のCが実際にはテンプレート ID であることを明確に説明していると思います。

于 2010-12-16T19:10:13.177 に答える