ポインタの減衰はテンプレートの推定よりも優先されます
文字列を操作するコードを作成する場合、オーバーロードしようとするジレンマに遭遇するのが一般的です配列ベースと非配列ベースの両方の文字列表現に対応する関数では、予期しない結果が生じる可能性があります。
この特定のシナリオでは、文字の配列の長さを出力するために初期関数 foo が定義されています。
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N-1 << std::endl; }
この関数は文字の配列を受け入れます。そして配列の長さを出力します。ただし、配列以外の文字列も処理できるように foo を拡張すると、あいまいさが生じます。
void foo(const char* s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
2 番目の foo オーバーロードは、配列以外の文字列を処理することを目的としています。文字列ですが、驚くべきことに、この拡張機能により、配列と非配列の両方で元のオーバーロードがバイパスされます。 strings:
foo("hello") // prints raw, size=5
この予期しない動作は、ポインター減衰の概念に由来しています。配列は本質的に最初の要素へのポインタであり、配列からポインタへの変換は非常に低コストの操作です。その結果、コンパイラは、配列引数からの暗黙的な変換が必要であっても、ポインター パラメーターを受け入れるオーバーロードを優先します。
配列ベースのオーバーロードが配列に使用される場合に望ましい動作を保証するには、次のようにします。追加のオーバーロードを導入する必要があります:
template <typename T> auto foo(T s) -> std::enable_if_t<std::is_convertible<T, char const*>{}> { std::cout << "raw, size=" << std::strlen(s) << std::endl; }
このオーバーロードはテンプレート推定を使用し、その適用範囲を文字ポインターに変換できる型に制限します。部分的な順序付けにより、コンパイラは引数の型に基づいて適切な foo 関数を正しく選択するようになりました。
以上がC 関数のオーバーロードでポインタの減衰がテンプレートの推定をオーバーライドするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。