web-dev-qa-db-ja.com

プログラム定義型に対するstdの関数テンプレートの特殊化は、C ++ 20では許可されなくなりましたか?

cppreference.com からの引用:

テンプレート特殊化の追加

宣言が依存している場合にのみ、標準ライブラリ| class(C++ 20)|のテンプレートのテンプレート特殊化を名前空間stdに追加できます。少なくとも1つのプログラム定義型と特殊化は、そのような特殊化が禁止されている場合を除き、元のテンプレートのすべての要件を満たします。

C++ 20以降、ユーザー定義型のstd名前空間に関数テンプレートの特殊化を追加することは許可されなくなりますか?もしそうなら、それは既存のコードの多くの部分が壊れる可能性があることを意味しますか? (一種の「根本的な」変更であるように思えます。)さらに、このようなコードに未定義の動作を注入し、コンパイルエラーを引き起こしません(警告が期待されます)。

25
Daniel Langr

今のところ、そのように見えます。以前は[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++コーディング標準:「オーバーロードの解決では、関数テンプレートの明示的な特殊化は考慮されません。オーバーロード解決が関数テンプレートを選択した後にのみ、明示的な特殊化が考慮されます。」
24
NathanOliver

それほど過激ではありません。この変更は、 Walter E. Brownのこの論文 に基づいています。論文はかなり深く理論的根拠になりますが、最終的には次のように要約されます。

  1. 関数テンプレートの特殊化は、カスタマイズポイントとしてはかなり不十分です。その点で、オーバーロードとADLははるかに優れています。このペーパーで説明されている他のカスタマイズポイントもあります。
  2. 標準ライブラリは、この貧弱なカスタマイズポイントに既に依存しすぎていません。
  3. 実際に導入された文言の変更により、明示的に許可されている場合、宣言全体を(特殊化だけでなく)名前空間stdに追加できます。そのため、betterカスタマイズポイントがあります。

#1と#2を考えると、既存のコードが壊れることはまずありません。または、少なくとも、これが大きな問題になるには十分ではありません。 autoregisterを使用したコードも過去に「壊れた」が、そのごくわずかなC++コードは進行を止めなかった。

15
StoryTeller