2

古いコードをクリーンアップしているときに問題が発生しました。これは機能です:

uint32_t ADT::get_connectivity_data( std::vector< std::vector<uint8_t> > &output )
{
    output.resize(chunks.size());
    for(chunk_vec_t::iterator it = chunks.begin(); it < chunks.end(); ++it)
    {
        uint32_t success = (*it)->get_connectivity_data(output[it-chunks.begin()]);
    }
    return TRUE;
}

私が興味を持っているのは、for ループをクリーンアップしてラムダ式にすることですが、正しい引数を get_connectivity_data に正確に渡す方法にすぐに行き詰まりました。get_connectivity_data は参照によって std::vector を受け取り、いくつかのデータで埋めます。出力には、各「チャンク」の std::vector が含まれます。

基本的に、これに対する私の結論は、コードをそのままにしておく方がはるかに簡単で、クリーンで、短いということでした。

編集:

したがって、私が想像していた私の質問に対する最も近い答えは次のとおりです。

 std::for_each( chunks.begin(), chunks.end(), 
                   bind( &chunk_vec_t::value::type::get_connectivity_data, 
                         _1, 
                         output[ std::distance( _1, chunks.begn() ] 
                       )
                 );

それでも、そのコードはコンパイルされません。コンパイルできるようにコードにいくつかの変更を加えましたが、2 つの問題が発生しました。

  1. _ 1 はスマート ptr であり、std::distance は機能しませんでした。開始点として &chunks[0] を使用する必要があったと思います
  2. _ 1 はスマート ポインターであるため、次のことを行う必要がありました。

zip_ iterators に関する答えは、さらに詳しく読んで、この特定の用途に必要な余分なコードの量がかなりのものであることを発見するまで (これとあれをバインドするなど)、良さそうに見えました。

EDIT2:

ここと下に投稿した、余分な構文が少なく、明確な許容可能な解決策を見つけました。

std::transform(chunks.begin(), chunks.end(), back_inserter(tmp), boost::bind(&ADTChunk::get_connectivity_data, _1) );
4

6 に答える 6

3

ちょっとした作業の後、私はこの解決策を思いつきました:

std::transform(chunks.begin(), chunks.end(), back_inserter(tmp), boost::bind(&ADTChunk::get_connectivity_data, _1) );

get_connectivity_data を参照によって取得する代わりに std::vector を返すように変更する必要がありました。また、チャンクの要素を Loki::SmartPtr ではなく boost::shared_ptr に変更する必要がありました。

于 2008-10-23T19:15:17.973 に答える
2

クラス全体のコードを見なければ、何が機能するかを判断するのは困難です。個人的には、この場合は BOOST_FOREACH の方がクリーンだと思いますが、参考までに、ラムダを使用してこのようなことを試してみるかもしれません (テスト コンパイルはできないことに注意してください)。

uint32_t ADT::get_connectivity_data( std::vector< std::vector<uint8_t> > &output )
{
    using namespace boost::lambda;

    output.resize( chunks.size() );

    std::for_each( chunks.begin(), chunks.end(), 
                   bind( &chunk_vec_t::value::type::get_connectivity_data, 
                         _1, 
                         output[ std::distance( _1, chunks.begn() ] 
                       )
                 );
    return TRUE;
}
于 2008-10-22T15:02:33.663 に答える
2

最善の方法はコードをそのままにしておくことだと考えたのは正しかったと思います。(a) それを書いていて、(b) 解決しようとしている正確な問題を理解しているときに、それを理解するのに苦労している場合は、3 年後に誰かがやって来たときに、それがどれほど難しいか想像してみてください。あなたが書いた問題と解決策の両方を理解する必要があります。

于 2008-10-22T07:32:08.690 に答える
1

ラムダに関してあなたが何を推進しているのかはよくわかりませんが、STLコンテナーを含むコードのクリーンアップについていくつかの一般的な提案をすることができます.

すべての STL コンテナー タイプの typedef を使用します。

typedef std::vector<uint8_t> Chunks;
typedef std::vector<Chunks> Output;
uint32_t ADT::get_connectivity_data( Output &output )

Boost の使用について話しているので、Boost.Foreachを使用します。

BOOST_FOREACH(chunk_vec_t::value_type &chunk, chunks)
  uint32_t success =
    chunk->get_connectivity_data(output[std::distance(&chunk, chunks.begin())]);

「ラムダ」のことを暗闇の中で突き刺します:

typedef const boost::function2<uint32_t, chunk_vec_t::value_type, Chunks>
  GetConnectivity;
uint32_t ADT::get_connectivity_data(Output &output, GetConnectivity &getConnectivity)
{
  output.resize(chunks.size());
  BOOST_FOREACH(chunk_vec_t::value_type &chunk, chunks)
    uint32_t success =
      getConnectivity(chunk, output[std::distance(&chunk, chunks.begin())]);
  return TRUE;
}

次に、次のように呼び出すことができます。

get_connectivity_data(output,
  boost::bind(&chunk_vec_t::value_type::get_connectivity_data, _1, _2));
于 2008-10-22T07:19:14.673 に答える
1

実際に行っているのは、2 つのコンテナーに対して並行して操作を実行することです。これが、boost::zip_iterator が設計された目的です。

ただし、コンテナーを並行して処理する必要がある唯一の理由は、Chunk::get_connectivity_data が out パラメーターを取得するためです。値で返される場合 (例外を使用してエラーを報告する)、単に挿入反復子を使用できます。

于 2008-10-22T08:32:48.410 に答える
1

何らかの理由で、STL の初心者は常に、より読みやすい (そして一定時間の) operator[] の代わりに vector::iterator を使用することを主張します。この式it-chunks.begin()は、元の作成者に、賢いコーダー ゲームに既に負けており、控えめなインデックスが必要であることを伝える必要がありました。

for (size_t i = 0, size = chunks.size(); i < size; ++i)
{
    chunks[i]->get_connectivity_data(output[i]);
} 

OP は、偽の戻りコードを失い、これを const メンバー関数にすることも検討する場合があります。

于 2008-10-22T18:57:50.957 に答える