1. ホーム
  2. c++

[解決済み] C++11で削除された関数がオーバーロードの解決に参加するのはなぜですか?

2023-02-14 05:56:30

質問

なぜ C++11 では " を使用しています。 delete d" 関数が過負荷の解決に参加するようになりました。 ?

なぜこれが有用なのでしょうか?あるいは言い換えれば、なぜ完全に削除されるのではなく、隠されるのでしょうか?

どのように解決するのですか?

の目的の半分は = delete 構文の目的の半分は、特定のパラメータで特定の関数を呼び出さないようにすることです。これは主に、ある特定のシナリオで暗黙のうちに変換されるのを防ぐためです。特定のオーバーロードを禁止するためには、オーバーロードの解決に参加する必要があります。

引用した回答は、完璧な例を示しています。

struct onlydouble {
  onlydouble(std::intmax_t) = delete;
  onlydouble(double);
};

もし delete が関数を完全に削除した場合、その分 = delete の構文はこれと同等になります。

struct onlydouble2 {
  onlydouble2(double);
};

こんなこともできるんですね。

onlydouble2 val(20);

これは合法的なC++です。コンパイラはすべてのコンストラクタを調べますが、どれも直接整数型を取りません。しかし、そのうちのひとつは暗黙の変換の後にそれを取ることができます。だから、それを呼び出すのです。

onlydouble val(20);

これは ではない 合法的な C++ ではありません。コンパイラはすべてのコンストラクタを調べ、その中には delete d のものも含めてすべてのコンストラクタを調べます。これは、完全に一致する std::intmax_t (これはどんな整数リテラルにも正確にマッチします)。そのため、コンパイラはそれを選択し、すぐにエラーを出します。 delete d 関数を選択したためです。

= delete は、単に「これは存在しない」という意味ではなく、「私はこれを禁止する」という意味で、より強い表現です。

私は、C++ 標準がなぜ = delete は "this does not exist" の代わりに "I forbid this" を意味すると言っているのかを尋ねていました。

それは、"this does not exist.と言うのに特別な文法を必要としないからです。 はできません。 を表すものです。ですから、私たちは、"I forbid this"と言うために特別な文法を取得し、他のものは取得しないのです。

明示的に"this does not exist"の文法を持つことで得られる唯一の機能は、誰かが後でそれを存在すると宣言することを防ぐことでしょう。そしてそれは、それ自身の文法を必要とするほど有用ではありません。

コピーコンストラクタが存在しないことを宣言する方法はありませんし、その存在は無意味な曖昧さを引き起こす可能性があります。

コピーコンストラクタは特殊なメンバ関数です。すべてのクラス は常に はコピー コンストラクタを持っています。ちょうど、コピー代入演算子、移動コンストラクタなどが常にあるようにです。

これらの関数は存在します。問題は、それらを呼び出すことが合法であるかどうかだけです。もし、あなたが = delete が存在しないことを意味すると言おうものなら、仕様書は関数が存在しないことが何を意味するのかを説明しなければならないでしょう。これは、仕様が扱う概念ではありません。

まだ宣言/定義されていない関数を呼び出そうとすると、コンパイラはエラーになります。しかし、エラーになるのは 未定義識別子 のためであり、quot;function doesn't exist"エラーのためではありません(たとえコンパイラがそのように報告したとしても)。さまざまなコンストラクタはすべてオーバーロード解決によって呼び出されるため、それらの "存在" はその点では処理されます。

すべての場合において、識別子を介して宣言された関数、またはコンストラクタ/デストラクタ (これも識別子を介して宣言され、単なる型識別子) が存在します。演算子のオーバーローディングは、構文上の糖分の後ろに識別子を隠しますが、それはまだそこにあります。

C++ 仕様は、存在しない関数という概念を扱うことができません。オーバーロードの不一致は扱えます。しかし、存在しないものについてはわかりません。そこで = delete は、あまり役に立たない "pretend I never wrote this line." よりも、はるかに役に立つ "attempts to call this fail" の観点から定義されています。

そしてもう一度、最初の部分を読み直してみてください。あなたは はできません。 を "function doesn't exist." とすることはできません。それがそのように定義されているもう一つの理由です。 = delete 構文の主な用途のひとつは、特定のパラメータタイプを使用するようユーザに強制したり、明示的にキャストしたりすることです。基本的には、暗黙の型変換を回避するためです。

あなたの提案はそれをしないでしょう。