2017-02-19 13 views
16

抜粋[function.objects]:メンバー以外の関数でdeleteを使用するポイントは何ですか?標準の20.12から

template <class T> reference_wrapper<T> ref(T&) noexcept; 
template <class T> reference_wrapper<const T> cref(const T&) noexcept; 
template <class T> void ref(const T&&) = delete; 
template <class T> void cref(const T&&) = delete; 

Iは、メンバ関数のコンテキストで=deleteを見慣れています。意図は、コンパイラによって提供された操作を禁止することです。例えば、クラスをコピー不可能または不可能にする。

しかし、この文脈では、意図は意図の文書であるように見えます。これは正しいですか?メンバー以外の機能に=deleteを使用することが望ましい、望ましい、または避けられない場合はありますか?

+7

関数が引数のセットが大きすぎると考えるすべての場合に、この関数を使用できます。だからあなたは邪悪な議論を取り、それらに合った削除された機能を作りますが、より良いものです。たとえば、 'f(int *)'が '0'を受け入れるのを防ぐ(nullポインタに対して' nullptr'だけを受け入れる)ことができます。したがって、 'f(int)= delete;'オーバーロードを追加することができます。 –

答えて

21

constの有用な機能の1つは、テンポラリがconstへの参照にバインドできることです。だから、これは動作します:

void foo(const int&); 
foo(42); // ok 

一時的42が関数の参照パラメータにバインドされ、その寿命は、その参照パラメータに結ばれていること。

今、std::cref()を考えてみましょう。目標はreference_wrapperをどこかに渡すことです。そのため、基礎となる参照が生き続ける必要があります。このオーバーロードが発生したばかりの場合:

次に、std::cref(42)と書くことができます。それはうまくいくでしょう、私はstd::reference_wrapper<const int>を返すでしょう - それはぶら下がっている参照を除いて。そのコードがこれまで通り働く可能性はありません。その明白なバグを修正するための努力において

、我々としても、このオーバーロードがあります。

template <class T> void cref(const T&&) = delete; 

、我々は明示的に削除(または削除済みとして定義する)のオーバーロードは、任意の右辺値を取っているしていること。今、過負荷解決を行うとき、私はrvalueを渡すと、この2番目の過負荷が優先され、その過負荷はうまく形成されず、コンパイラは私のバグを知らせます(私の代わりにcref(42)!なぜ私がオブジェクトを持っていないのか理解しようとしているgdbと数時間を費やす必要があります。


同じ思考プロセスは、任意の関数を適用することができます。あなたがうまくいくかもしれないいくつかの暗黙的な変換シーケンスがあります。あなたが間違いなく罰金ではなく、明示的に除外したいものもあります。それは=deleteのためです。

関連する問題