cppreference.com からの引用:
テンプレート特殊化の追加
宣言が依存している場合にのみ、標準ライブラリ| class(C++ 20)|のテンプレートのテンプレート特殊化を名前空間stdに追加できます。少なくとも1つのプログラム定義型と特殊化は、そのような特殊化が禁止されている場合を除き、元のテンプレートのすべての要件を満たします。
C++ 20以降、ユーザー定義型のstd
名前空間に関数テンプレートの特殊化を追加することは許可されなくなりますか?もしそうなら、それは既存のコードの多くの部分が壊れる可能性があることを意味しますか? (一種の「根本的な」変更であるように思えます。)さらに、このようなコードに未定義の動作を注入し、コンパイルエラーを引き起こしません(警告が期待されます)。
今のところ、そのように見えます。以前は[namespace.std]が含まれていました
プログラムは、宣言がユーザー定義型に依存し、元のテンプレートの標準ライブラリ要件を満たし、明示的に禁止されていない場合のみ、名前空間stdにテンプレート特殊化標準ライブラリテンプレートの場合を追加できます。 。
While 現在のドラフトの状態
明示的に禁止されていない限り、プログラムは(a)追加された宣言が少なくとも1つのプログラム定義型に依存し、(b)特殊化を条件として、テンプレート特殊化を追加する場合があります標準ライブラリクラステンプレートの場合元のテンプレートの標準ライブラリ要件を満たしています。
重点鉱山
そして、それは紙のように見えます あなたは標準関数テンプレートを特化しないでください! by Walter E. Brownがそれを担当しています。その中で、彼はこれが変更されるべきいくつかの理由を詳細に述べています:
- ハーブサッター:「専門分野は過負荷に関与しません。 [...]関数のベーステンプレートをカスタマイズし、そのカスタマイズをオーバーロード解決に参加させる(または完全一致の場合に常に使用する)場合は、特殊化ではなく、単純な古い関数にします。また、オーバーロードを提供する場合は、専門化も提供しないでください。」
- David Abrahams:「関数テンプレートの特殊化を使用するのは間違っています[なぜなら]オーバーロードと悪い方法でやり取りするからです。 [...]たとえば、通常の
std::swap
にとってstd::vector<mytype>&
、オーバーロードの解決時にスペシャライゼーションは考慮されないため、スペシャライゼーションは標準のベクトル固有のswap
よりも選択されません。」- ハワード・ヒナント:「この問題は長い間解決されてきました。 。 。 。この分野におけるデイブの専門家の意見/回答はご自身の責任で無視してください。」
- エリック・ニーブラー:「(そのために)C++がテンプレート内の関数呼び出しを解決する決定的に不安定な方法。 。 。 、[w] e [...]に関連付けられた名前空間[...]で定義されている可能性のあるオーバーロードを見つけるために
swap
の非修飾呼び出しを行い、using std::swap
そのため、そのようなオーバーロードがないという偶然に、std名前空間で定義されているデフォルトバージョンを見つけることができます。- 高整合性C++コーディング標準:「オーバーロードの解決では、関数テンプレートの明示的な特殊化は考慮されません。オーバーロード解決が関数テンプレートを選択した後にのみ、明示的な特殊化が考慮されます。」
それほど過激ではありません。この変更は、 Walter E. Brownのこの論文 に基づいています。論文はかなり深く理論的根拠になりますが、最終的には次のように要約されます。
#1と#2を考えると、既存のコードが壊れることはまずありません。または、少なくとも、これが大きな問題になるには十分ではありません。 auto
とregister
を使用したコードも過去に「壊れた」が、そのごくわずかなC++コードは進行を止めなかった。