2016-07-08 8 views
4

私はFooのベクトルを手元に持っています。それをBarのベクトルとconstのベクトルに変換したいと思います。私は考えることができる最善の方法は次のとおりです。constベクトルに変換する

Bar foo2bar(const Foo& foo); 

std::vector<Foo> foos = {...}; 

const std::vector<Bar> bars = [&foos] { 
    std::vector<Bar> bars; 
    bars.reserve(foos.size()); 
    std::transform(foos.cbegin(), foos.cend(), 
        std::back_inserter(bars), 
        foo2bar); 
    return bars; 
}(); 

そして私は、ラムダの戻り値は、ほとんどのコンパイラで省略されるべきだと思うので、これは理想に近いはずです。唯一の欠点はおそらくラムダを作成する必要があることですが、それはあまり問題ではないと思います。

は、このアプローチを持つ任意の陰湿な問題があり、(例えば、より速く、クリーナー)任意のより良い方法はありますか? C++ 11が利用可能です。

答えて

4

あなたの最も簡単な解決策は完全にconst要件をドロップすることです。 constへの参照を他のスコープに公開することはできます。それに失敗

、これは問題ないはずです。ラムダ本体はおそらくインライン展開され、ラムダの「作成」はコンパイル時のプロセスであり、戻り値はすべて移動または省略されます。あなたのアプローチは、実際には非常にエレガントです。

+0

少し時代遅れだが、スーパーセーフなコードになる)ので、何かを理解しようとする必要がある。提案していただきありがとうございます! –

+0

@ZizhengTai:そうです、可能であれば、私は 'const'を提唱しています。しかし、線を引く場所を知る必要があります。 –

2

あなたは本当に、あなたがブーストのtransform_iteratorのために達する可能性がある、ラムダのアイデアを我慢できない場合は、次の

#include <vector> 
#include <boost/iterator/transform_iterator.hpp> 

struct Foo {}; 
struct Bar {}; 

Bar foo2bar(const Foo& f) { 
    return Bar {}; 
} 

int main() 
{ 
    std::vector<Foo> foos = { }; 

    using boost::make_transform_iterator; 
    const std::vector<Bar> bars (make_transform_iterator(foos.begin(), &foo2bar), 
           make_transform_iterator(foos.end(), &foo2bar)); 
} 

しかし、ラムダは、最適化後も、パフォーマンスペナルティを持っていないし、間違いなく少ない不可解であるので、私は励ましますそれ。

1

代わりにあなたが変換演算子としてあなたFooクラスにごfoo2bar()機能を移動することができ:多分(うん、それはオブジェクトは、可能な限り `const`をマークする必要があります私のチームのスタイルガイドラインです

struct Bar {}; 
struct Foo 
{ 
    // conversion opertor 
    operator Bar() const 
    { 
     // code to create Bar bar 
     return bar; 
    } 
}; 

int main() 
{ 
    std::vector<Foo> foos = {}; 

    const std::vector<Bar> bars(foos.begin(), foos.end()); 
} 
関連する問題