50

この質問を読んで疑問に思いました: クラス テンプレートのオーバーロードを禁止する技術的な理由はありますか?

オーバーロードとは、たとえば、同じ名前で異なるパラメーターを持つ複数のテンプレートを持つことを意味します。

template <typename T>
struct Foo {};

template <typename T1, typename T2>
struct Foo {};

template <unsigned int N>
struct Foo {};

コンパイラはオーバーロードされた関数と関数テンプレートを処理しますが、クラス テンプレートに同じ手法 (名前マングリングなど) を適用することはできないのでしょうか?

最初は、テンプレート識別子を単独で取得すると、あいまいさの問題が発生する可能性があると考えていましたが、これが発生するのはテンプレート テンプレート引数として渡す場合のみであるため、パラメーターの型を使用して適切な値を選択できます。オーバーロード:

template <template <typename> class T>
void A {};

template <template <unsigned int> class T>
void B {};

A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>

そのような機能は便利だと思いますか? 現在の C++ でこれが不可能な「良い」(つまり技術的な) 理由はありますか?

4

3 に答える 3

38

Templates the Complete Guide ( Amazon ) のセクション 12.5には、次の引用が含まれています。

なぜクラス テンプレートだけが部分的に特殊化できるのか疑問に思うかもしれません。その理由は主に歴史的なものです。関数テンプレートに対して同じメカニズムを定義することはおそらく可能です (第 13 章を参照)。

関数テンプレートのオーバーロードの効果はいくつかの点で似ていますが、微妙な違いもいくつかあります。これらの違いは主に、使用が発生したときにプライマリ テンプレートを検索する必要があるという事実に関連しています。特殊化は、使用する必要がある実装を決定するために、後でのみ考慮されます。

対照的に、オーバーロードされたすべての関数テンプレートは、それらを検索してオーバーロード セットに入れる必要があり、異なる名前空間またはクラスから取得することができます。これにより、意図せずにテンプレート名をオーバーロードする可能性が多少高くなります。

逆に、クラス テンプレートのオーバーロードの形式を許可することも考えられます。次に例を示します。

// invalid overloading of class templates
template<typename T1, typename T2> class Pair; 
template<int N1, int N2> class Pair; 

ただし、そのようなメカニズムが差し迫って必要とされているようには見えません。

さらに、C++ の設計と進化( Amazon ) には、セクション 15.10.3 にこの引用が含まれています。

したがって、テンプレートを「特殊化」するためのメカニズムが必要であると結論付けました。これは、一般的なオーバーロードを受け入れるか、より具体的なメカニズムによって行うことができます。私が特定のメカニズムを選択したのは、主に C の不規則性によって引き起こされる不規則性に対処していると考えたためであり、オーバーロードの提案は常に抗議のうなり声を生み出すからです。私は用心深く、保守的になろうとしていました。私は今それを間違いだと考えています。当初定義された特殊化は、言語の残りの部分とうまく適合しない、制限された異常な形式のオーバーロードでした。

大胆強調鉱山。私はこれを、クラスの特殊化よりも関数のオーバーロードの解決を実装する (そしてユーザーが正しく理解する) のが難しいと言っていると解釈します。したがって、おそらく実際の技術的な障害 (関数テンプレートの部分的な特殊化と同様) ではなく、歴史的な事故です。

于 2012-08-15T12:19:18.597 に答える
19

型パラメーター、非型引数、およびテンプレート テンプレート パラメーターを「オーバーロード」することはできませんが、可変個引数テンプレートを特殊化できます。

template <typename... T>
struct Foo;

template <typename T1>
struct Foo<T1> {};

template <typename T1, typename T2>
struct Foo<T1,T2> {};
于 2012-08-15T12:21:07.840 に答える