8

これは非常に衒学的ですが、C++03 では、プログラムが名前空間でテンプレート関数をオーバーロードする(特化しない)ことは明らかに非準拠でした:ここでの言及とcomp.lang.c++.moderated に関する長い議論を参照してください。std

つまり、これは問題ありませんでした:

namespace std
{
    template <>
    void swap (Foo & f, Foo & g)
    {
       // ...
    }
}

しかし、これはそうではありませんでした(私が正しく理解していれば...):

namespace std
{
    template <typename T>
    void swap (TempateFoo<T> & f, TempateFoo<T> & g)
    {
       // ...
    }
}

これは C++11 でも当てはまりますか? また、これはテンプレート クラス (のようなstd::hash) にも適用されますか、それともテンプレート関数だけに適用されますか?

編集:また、後者が実際に物事を壊すような標準ライブラリの実装の例はありますか? そうでない場合、上記の 2 番目のケースのようにオーバーロードを禁止する特定の理由はありますか? (理論上、何が壊れる可能性があるのでしょうか?)

4

2 に答える 2

8

C ++で関数テンプレートの部分的な特殊化を定義することはできないため、2番目の例では、特殊化ではなくオーバーロードを定義します。標準では名前空間に特殊化を追加することしか許可されていないためstd、オーバーロードは違法です。

これはC++11でも当てはまりますか?

はい。

また、これはテンプレートクラス(std :: hashなど)にも適用されますか、それともテンプレート関数だけに適用されますか?

とにかくクラステンプレートをオーバーロードすることはできません。関数をオーバーロードすることしかできません。同じルールが適用されますが、特殊化がユーザー定義の(非標準を意味する)タイプに依存する場合にのみ、クラステンプレートを特殊化できます。

上記の2番目のケースのように過負荷を許可しない特定の理由はありますか?(理論的には何が壊れる可能性がありますか?)

一例として、実装は関数のアドレスを取得したい場合がありますが、関数をオーバーロードした場合、アドレスを取得するとあいまいさが生じ、コンパイルに失敗する可能性があります。つまり、標準ライブラリの有効なコードが壊れただけです。

于 2013-02-27T13:22:30.310 に答える
6

n3376 17.6.4.2.1

特に指定がない限り、名前空間stdまたは名前空間std内の名前空間に宣言または定義を追加する場合、C++プログラムの動作は未定義です。プログラムは、宣言がユーザー定義型に依存し、特殊化が元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合にのみ、任意の標準ライブラリテンプレートのテンプレート特殊化を名前空間stdに追加できます。

17.6.4.2.2

C ++プログラムの動作は、次のように宣言されている場合は未定義です。

—標準ライブラリクラステンプレートの任意のメンバー関数の明示的な特殊化、または

—標準ライブラリクラスまたはクラステンプレートのメンバー関数テンプレートの明示的な特殊化、または

—標準ライブラリクラスまたはクラステンプレートのメンバークラステンプレートの明示的または部分的な特殊化。

プログラムは、宣言がユーザー定義型の名前に依存し、インスタンス化が元のテンプレートの標準ライブラリ要件を満たしている場合にのみ、標準ライブラリで定義されたテンプレートを明示的にインスタンス化できます。

于 2013-02-27T05:31:29.217 に答える