2016-12-27 16 views
3

は、一例として、STDの二つの異なるタイプ::ベクトルである:それらの間に割り当てるstd :: vector <T>とstd :: vector <std :: reference_wrapper <T>>を比較して割り当てる方法は?ここ

std::vector<std::reference_wrapper<MyClass>> rv; 
std::vector<MyClass> v; 

可能な方法は次のとおり

for (const auto& mc : rv) { 
    v.push_back(mc.get()); 
} 

それが動作します。しかし、醜い、おそらく遅い。比較と同じ:

bool is_same(std::vector<MyClass>& v, std::vector<std::reference_wrapper<MyClass>>& rv) { 
    if (v.size()!=rv.size()) { 
     return false; 
    } 
    for (size_t i = 0; i < v.size(); v++) { 
     if (v[i]!=rv[i].get()) { 
      return false; 
     } 
    } 
    return true; 
} 

この作業を行うには良い方法がありますか?スマートでクイック。

答えて

5

std::reference_wrapperは、それが保持するタイプへの参照に暗黙的に変換可能であるため、MyClassに1を割り当てることができます。あなたが本当に割り当てる必要がある場合

std::vector<MyClass> v(begin(rv), end(rv)); 

または、:: だから他に1を初期化するためのより良い方法は、適切なベクターコンストラクタです

v.assign(begin(rv), end(rv)); 

あなたはstd::mismatchアルゴリズムを適用することによって、比較を行うことができます、再びstd::reference_wrapperが提供する暗黙的な変換のおかげで:親指の一般的なルールとして

bool is_same(std::vector<MyClass> const& v, std::vector<std::reference_wrapper<MyClass>> const& rv) { 
    return v.size() == rv.size() && 
     end(v) == std::mismatch(begin(v), end(v), begin(rv), end(rv)).first; 
} 

は、それはですあなた自身でループを書く前に、標準のアルゴリズムライブラリを参照するのは良いことです。これは、動詞と名詞を計算ステップに与えることによって、あなた自身のコードをより読みやすくします。標準ライブラリが提供できる最適化を可能にする利点があります。が指摘


cppleaner として、私は自分自身をより密接にライブラリを相談している必要があります。

bool is_same(std::vector<MyClass>& v, std::vector<std::reference_wrapper<MyClass>>& rv) { 

    return std::equal(begin(v), end(v), begin(rv), end(rv), 
     [](const MyClass& c, const std::reference_wrapper<MyClass>& rc) { 

     return c == rc.get(); 
    }); 
} 

代わりに、カスタム書くことができます:

class MyClass { 
    bool operator ==(const MyClass&); 
}; 

bool operator != (const MyClass&, const MyClass&); 
bool operator == (const MyClass&, const std::reference_wrapper<MyClass>&); 
bool operator == (const std::reference_wrapper<MyClass>&, const MyClass&); 
bool operator != (const MyClass&, const std::reference_wrapper<MyClass>&); 
bool operator != (const std::reference_wrapper<MyClass>&, const MyClass&); 

およびクライアントコード(このis_samestd::equal

return std::equal(begin(v), end(v), begin(rv), end(rv)); 
+0

v.size()== rv.size()&&ではなく 'std :: equal(begin(v)、end(v)、begin(rv)、end(rv))' end(v)== std :: mismatch(begin(v)、end(v)、begin(rv)、end(rv))。 'std :: equal'だけでなく、各反復で1つの反復子の比較を保存します。 – cpplearner

+0

@cpplearner - ありがとう。私はコーヒーを飲む前にこの答えを書いてはいけません。 – StoryTeller

0

慣用的is_same実装に簡単な呼び出しによって、より容易に実現することができます冗長です:実装を操作として使うことができます):

bool is_same(const std::vector<MyClass>& v, 
      const std::vector<std::reference_wrapper<MyClass>>& rv) { 
    return v == rv; 
} 

注:可能であれば、引数にconstを使用することを検討してください。

関連する問題