2016-03-27 17 views
-3

のは、私はクラスがあるとしましょう:明確に定義されたoperator +=非友人シングルライン演算子+過負荷+ =

class A 
{ 
    //... 
}; 

A& operator +=(const A&) {return *this;} //class without members 

それでは、またoperator+をオーバーロードしてみましょう(非友人として)。ここには良いです

A operator +(const A& other) const 
{ 
    return auto(*this)(*this) += other; //error: invalid use of auto 
//   /\/\/\/\/\ /\  
//  type of *this || 
//     constructor call 
} 

auto:私は一時オブジェクト(ちょっとこれは汎用コードを作りたい)のコンストラクタを呼び出すために、クラス名を使用する必要はありません。試してみましょうdecltype (それは私が考えたものだ)

A operator +(const A& other) const 
{ 
    return decltype(*this)(*this) += other; //error: 'A& A::operator+=(const A&)' discards 
//   /\/\/\/\/\/\/\ /\      qualifiers [-fpermissive] return 
//   type of *this ||      decltype(*this)(*this) += other; 
//     constructor call         ^
} 

この

*thisの外型を取得するために管理しますが、 operator+はconstとして宣言されているので、私たちは推測 const Aを得ました。だから続けよう:

A operator +(const A& other) const 
{ 
    return typename std::remove_const<decltype(*this)>::type(*this) += amount; 
    //same error as previous 
} 

今私は気が狂った。でも、それはまだ 修飾子を破棄し、私はconst性を取り除くと思いました。まあ、多分私がやっていたのはちょうどキャスティングだったからかもしれません。とてもばかげている。私は(タイプ以外に)持っている::コンストラクタコードを生成しなければならないコンストラクタを呼び出すには(そう、私も、コンストラクタのエイリアスを作ってみましたが、この時点で、私は懸命に失敗しました)。私の壊れた脳はあきらめたが、私の意識の残りの部分は私に与えたソリューション(書面での一般的なので、それは良いことだ):私は終わったものだ

// outside of class 
template<class A> 
inline A&& make_rvalue(A copy) 
{ 
    return std::move(copy); 
} 

// inside of class 
A operator +(const A& other) const 
{ 
    return make_rvalue(*this) += other; // such generic code 
} 

。しかし、他の関数呼び出しを伴わないトリックはありますか?

編集:私はこれを行うための古典的な方法を知っているが、私は検索すると、以下の通りである:

  • オペレータが{return /*...*/;}
  • に低減され、クラスメソッドまたはグローバル関数
  • の名前を含みません他のタイプの過負荷を考慮して取る - それは交換ARとターゲット演算子を呼び出しMatrixクラス(ただし、プロキシ演算子ではあまり役立ちませんconst int&上、class A != class Bいるので、値で引数intを引数を取ることができませんgumentsは
  • は、両方が
  • return文が与えられた[email protected]ためexacly同じである必要があり、同じreturn文を持つべきであるべきところ)操作([email protected] != [email protected]の(可能な)順番を考慮するのにかかる過負荷状態にしているすべてのクラスである)OKですoperator +=
+1

const refではなく、最初に値で引数を取るのはなぜですか? – Useless

+2

何を言っているのか分かりません。 –

+2

この '演算子+'は**一般的ではありません。それはタイプAのオブジェクトでトラフィックします。 A型の使用を避けるべき理由はありません。なぜなら、それが何であるかを正確に知っているからです。そしてジェネリックコードでさえ、あなたが扱っているタイプを知っているでしょう。この周回はすべて無意味です。 –

答えて

1

あなたはこのような関数を作成する場合:

template <typename T> 
T add(T temp,const T &b) 
{ 
    temp += b; 
    return temp; 
} 

あなたはこのようにそれを使用することができます

A operator+(const A& other) const { return add(*this,other); } 
+0

C++ 11が出て以来、このバージョンをよく使っています。私が検索したのは、 'return /*...*/; 'のバージョンです。 – xinaiz

+0

@BlackMoses:Ok、マッチするように答えを変えました。 –

1

私は思考/コーディングのこの行全体が間違った道を進んでされ言うように記録に行くつもりです。あなたは既に(この場合は)戻り値の型がAであることを知っています。あなたのコードでは、可能な限り最も複雑な、間接的な方法でAを言うに多くの仕事を入れているようです。

A operator +(const A& other) const { 
    A ret {*this}; 
    ret += other; 
    return ret; 
} 

あなたが本当にように見えるので、それから何かを使用していますので、私は、ブレース初期化子を使用(この場合には、それらのほとんどどれもが任意の本当の助けを提供していないにもかかわらず)は、C++ 11個の機能を使用したいですC++ 11。そして、いいえ、これは一つの行ではありませんが、それは読むことができます。

ジェネリックコードでも同じスタイルが問題ないことに注意してください。これは、同様にビットを簡素化することができるものの

template <class T> 
T operator+(T const &a, T const &b) { 
    T ret {a}; 
    ret += b; 
    return ret; 
} 

:再び

template <class T> 
T operator+(T ret, t const &b) { 
    ret += b; 
    return ret; 
} 

、我々は正確に何も失うん例えば、operator+の非加盟過負荷で、我々はこのような何かを持っているかもしれませんより古いコンパイラが問題なくコードを受け入れることができます。

+0

しかし、operator +に2つの型があり、操作の順序に大きな違いがある場合は、スワップされた引数を持つ実際の演算子を呼び出す可能性のある代理演算子の呼び出しについて考えてください - 単純なテンプレートは何が良い順序であるかを知りません。実際にプロキシかどうかわからなくても元のテンプレートと同じであってもかまいません。あまりにもあいまいで作業する。 – xinaiz

+0

@BlackMoses - はい、質問が異なる場合、答えは異なる可能性があります。しかし、そうではありません。 –

関連する問題