ホームページ  >  記事  >  バックエンド開発  >  C 関数のオーバーロードでポインタの減衰がテンプレートの推定をオーバーライドするのはなぜですか?

C 関数のオーバーロードでポインタの減衰がテンプレートの推定をオーバーライドするのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-21 16:11:14558ブラウズ

Why Does Pointer Decay Override Template Deduction in C   Function Overloading?

ポインタの減衰はテンプレートの推定よりも優先されます

文字列を操作するコードを作成する場合、オーバーロードしようとするジレンマに遭遇するのが一般的です配列ベースと非配列ベースの両方の文字列表現に対応する関数では、予期しない結果が生じる可能性があります。

この特定のシナリオでは、文字の配列の長さを出力するために初期関数 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。