3

私の問題はかなり単純です。文字列を返すメソッドを持つオブジェクトの動的配列があります。これらすべての文字列を連結したい。

文字列を返すメソッドを持つオブジェクトの代わりに文字列の配列がある場合、これは簡単な作業になります。

std::vector<std::string> v{ "f", "o", "o" };
std::string const x = std::accumulate(v.begin(), v.end(), std::string());

しかし、私の場合はむしろ次のようになります。

struct foo
{
    foo(std::string const & name) : name_(name) {}
    std::string const & name() const { return name_; }

    private:
        std::string const name_;
};

std::vector<foo> v{ foo("f"), foo("o"), foo("o") };

標準ライブラリのアルゴリズムは効率的であり、デバッグする必要がないと確信しているため、標準ライブラリのアルゴリズムを使用したいと思いますが、これは読みにくく、理解するのが難しすぎます。

std::vector<std::string> transformed(v.size());
std::transform(v.begin(), v.end(), transformed.begin(),
    [](foo const & f) { return f.name(); });
std::string const x = std::accumulate(transformed.begin(), transformed.end(),
    std::string());

将来のメンテナはおそらく (そして当然のことながら) 私を追い詰めて、簡単なタスクを不必要に複雑にしたことで顔を殴りつけるでしょう。

std::string x;
for(auto const & f : v)
    x += f.name();

ここで私が見ていない簡単なものはありますか、それとも標準ライブラリを休ませて for ループを使用する必要がある場合ですか?

4

4 に答える 4

6

STL の使用を主張している場合は、別のバージョンのstd::accumulate:

template< class InputIt, class T, class BinaryOperation >
T accumulate( InputIt first, InputIt last, T init, BinaryOperation op );

その後、コードは次のようになります

std::string const x = std::accumulate(v.begin(), v.end(), std::string(),
                         [](std::string a, foo const& b){return a += b.name();});

編集: おそらく、よりコピー省略に適した宣言

于 2013-10-14T16:53:18.127 に答える
2

forループアプローチを使用するだけです。読みやすく、デバッグやテストが必要なものではありません (少なくとも、何らかの独自のアルゴリズムを作成した場合と同じレベルではありません)。std ライブラリを利用するソリューションではないからといって、保守が容易で賢明なソリューションであるとは限りません。

于 2013-10-14T16:47:52.850 に答える
0

演算子 += と書くことができます。のようなもの

std::string & operator +=( std::string &s, const Foo &f )
{
   return ( s += f.name() );
}
于 2013-10-14T16:54:06.020 に答える
0

std::for_each、std::accumulate がどのようにパフォーマンスを向上させるのかわかりません (ベクトルはこれが問題になるほど大きいですか?)。重要な場合は、タイミング分析を実行することをお勧めします。

パフォーマンスが重要でない場合は、複雑さを使用するよりも読みやすさと保守性を重視します。

于 2013-10-14T17:01:41.537 に答える