2012-10-06 19 views
11

次の例に示すように、最近、私はC++の式に割り当てに関する議論が続いている:C++ 11と代入演算子に左辺参照修飾子を使用する必要がありますか?

string s1, s2, s3; 
(s1 + s2) = s3; 

を、左側に参照を(左辺値への代入演算子を制限することが可能です)。代入演算子を次のように宣言すると、コンパイラClangは、互換性のない型のためにエラーメッセージでコードを拒否します。

auto operator=(const string& rhs) & -> string&; 
auto operator=(string&& rhs) & -> string&; 

私はこれを見たことがありません。代入演算子にlvalue参照修飾子を使用しない理由はありますか(ほとんどのコンパイラではサポートが失われています)。

+5

1つの理由は、ほとんどのコンパイラが構文をまだサポートしていないことです。もう一つは、*大きな問題を解決しないということです。これは間違ってどのくらいの頻度で起こるのですか? –

+1

私はそれが起こると思います。 'if(somefunc()= value)'もちろん、ほとんどのコンパイラはこれに対して警告を出しますが、すべてのケースで警告するわけではありません。 –

答えて

4

いいえ、実際はありません。 lvalueまたはrvalue修飾子を使用して、lvalueまたはrvalueオブジェクトの正しいインタフェースを構築することは、constを使用する場合とまったく同じです。同様の方法でアプローチする必要があります。各関数は制限の対象となります。右辺値への代入は実際には意味がないので、禁止する必要があります。

*thisのコンパイラのサポートがほとんどないのは、thread_localのようなものです。コンパイラのほとんどの実装者は、「C++ 11から実装する機能」の最下部にあるようです。スタック。

+0

私の意見では最高の答えです。私は代入演算子に興味がありましたが、これは特別なメンバー関数であるためです。参照修飾子を使用すると、ルール5、継承、集約のメンバ変数または標準コンテナと標準ライブラリの使用に何らかの影響があります。しかし、私はこの情報を求めていたはずです。 – nosid

8

興味深い!私はこれも認識しておらず、探しているうちに私を連れて行きました(それは"Extending move semantics to *this"提案の一部でした)。表記は、8.3.5 [dcl.decl]パラグラフ4で定義されています。

とにかく、この機能について知っていれば、オーバーロードのために使うのが最も便利で、関数が呼び出されたオブジェクトが左辺値または右辺値の場合には異なる動作をする可能性があります。それを使用して、例えばオブジェクトが実際には左辺値である場合には、割り当ての結果を使用して実行可能な操作を制限することは不要です。たとえば、構文は右辺値に割り当てるから右辺値を返すようにしたいかもしれません:

struct T { 
    auto operator=(T&) & -> T&; 
    auto operator=(T&&) & -> T&; 
    auto operator=(T&) && -> T; 
    auto operator=(T&&) && -> T; 
}; 

ここでの意図は、割り当て結果から移動可能にすることです(それはそれの価値があるかどうか、しかし、私はありません確かに、最初に課題をスキップしないのはなぜですか?)。主にこの機能を使用を制限するために使用するとは思わない。

個人的には、時には右辺値から左辺値を保持する可能性があり、代入演算子はこれを行う方法です。あなたが関数に左辺値を渡す必要がありますが、あなたはそれで何かを使用しないわかっている場合たとえば、あなたが代入演算子を使用することができます左辺値のホールドを取得:

#include <vector> 
void f(std::vector<int>&); 
int main() 
{ 
    f(std::vector<int>() = std::vector<int>(10)); 
} 

これがかもしれ右辺値から左辺値を得る代入演算子の乱用が、偶然に起こる可能性は低い。したがって、代入演算子を左辺値にのみ適用するように制限することで、私は自分の道を離れてこれを不可能にしません。もちろん、代入から右値にrvalueを返すことでこれを防ぐこともできます。 2つの用途のどちらがより有用であるかは、考慮される可能性があります。

ところで、clangはバージョン2.9以降で引用した構文をサポートしているようです。

+5

私はむしろ明確なテンプレートを持っています。 T&as_lvalue(T && v){return v; } '関数は、あなたが割り当てで達成しようとしている地獄(move-unawareのために、' vector 'の無駄なコピーを含んでいるように見える)が何であるか疑問に思う私の仲間のコーダーの心にねじ込むよりも機能します。 – Xeo

3

私はあなたの提案についてのスーパー熱狂者ではない理由の1つはI'm trying to shy away from declaring special members altogetherです。したがって、代入演算子のほとんどは暗黙的に宣言されているため、ref-qualifierはありません。

もちろん、私がクラスやクラスのテンプレートを書き込むときには、所有権を管理することができます(上のリンクの結論を参照してください)。私は、これらの演算子を左辺値のみに宣言するように気を付けることができます。しかし、それはクライアントに影響を与えないので、あまり意味がありません。

+0

私はあなたに同意します。可能であれば、私は5のいずれかを宣言しないでください。しかし、コンパイラ生成代入演算子は左辺値の参照に限定されません。ほとんどの場合、下位互換性があります。 – nosid

関連する問題