ホームページ >バックエンド開発 >C++ >C のオーバーロード解決において、ポインタの減衰が推定されたテンプレートよりも優先されるのはなぜですか?

C のオーバーロード解決において、ポインタの減衰が推定されたテンプレートよりも優先されるのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-29 19:15:15855ブラウズ

Why Does Pointer Decay Take Precedence Over Deduced Templates in C   Overload Resolution?

ポインタの減衰と推定されたテンプレート: 優先順位のパズルを解く

C の領域では、関数のオーバーロードとテンプレートの推定の間の相互作用は次のようになります。時には予期せぬ結果を招くこともあります。代表的な例は、配列と生のポインターの両方を処理するために関数がオーバーロードされた場合に発生します。次のコードを考えてみましょう。

template <size_t N>
void foo(const char (&amp;s)[N]) {
    std::cout << "array, size=" << N - 1 << std::endl;
}

void foo(const char *s) {
    std::cout << "raw, size=" << strlen(s) << std::endl;
}

この関数は、最初は配列の長さを出力するために考案されましたが、非配列をサポートするように拡張されました。しかし、この拡張は不可解な曖昧さをもたらします。

foo("hello") // now prints raw, size=5

後者の方がパラメータとより正確に一致しているにもかかわらず、意図した「配列」バージョンではなく「生」オーバーロードが選択されるのはなぜでしょうか?答えは、ポインターの減衰 として知られる微妙な概念にあります。

ポインターの減衰は、配列から対応するポインターへの暗黙的な変換です。この場合、配列「hello」は、その最初の要素への const char * ポインターにサイレントに変換されます。結果として、ポインターを処理するオーバーロードが優先されます。

この動作は、 C での変換のコストに起因します。オーバーロードは、引数をパラメーターに変換するコストを最小限に抑えるために評価されます。この場合、配列からポインターへの変換は、配列から関数へのパラメーター変換よりもコストが低くなります。

この問題を回避するには、2 番目のオーバーロードもテンプレートとして定義できます。

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;
}

このアプローチでは、ポインター減衰変換が不要になるため、テンプレート バージョンが優先されます。

結論として、ポインター減衰が優先されます。推定されたテンプレートを超えることは、過負荷解決におけるコスト最小化原則の結果です。あいまいさを回避するには、関数をオーバーロードするときに暗黙的な変換とオーバーロードの種類の両方を考慮することが重要です。

以上がC のオーバーロード解決において、ポインタの減衰が推定されたテンプレートよりも優先されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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