2

大きな がありますstd::vector<int> aが、そのサブセットのみで作業したいと考えています。アイデアはstd::vector<reference_wrapper<int> > refa、上記のサブセットのみを含む を作成することでした (mwe では、すべての要素 1< a< 4)。次に、またはを引数としてrefa期待する関数に渡したいと思います (これらを とともに使用したいため)。かなり大きくなる可能性があるため、選択を複数回行うことは避けたいと思います。std::vector<int>std::vector<int>&aa

質問

refa関数に適切に渡すにはどうすればよいですか? 私が欲しいのはbar(refa)foobar(refa)働くことです。

関数を (あまり) 変更せずに、問題を解決するより良い方法はありますか?

コード

#include <functional>
#include <iostream>
#include <vector>


int foo(int &a)
{
  a++;
  return 0;
}

int bar(std::vector<int> &va)
{
  for(auto &vaa : va)
    vaa++;

  return 0;
}

int foobar(std::vector<int> va)
{
  for(auto &vaa : va)
    vaa++;

  return 0;
}



int main()
{
  std::vector<int> a= {1, 2, 3, 4, 5};
  std::vector<std::reference_wrapper<int> > refa;

  //Fill refa
  for(auto &aa : a)
    {
      if(aa>1 && aa<4) refa.push_back(std::ref(aa));
    }


  //works
  // for(auto &aa : refa)
  //   aa++;

  //works
  //  bar(a);

  //works, a unchanged
  //  foobar(a);

  //works
  // for(auto &aa : refa)
  //   foo(aa);

  //works                         
  // for(int &aa : refa)
  //  foo(aa)

  // does not work
  // conversion from vector<reference_wrapper<int> > to vector<int>& or vector<int> required
  bar(refa);
  //  foobar(refa);


  for(auto &aa : a)
    std::cout << aa << std::endl;


  return 0;
}

注記 intは、例を単純にするためにここでのみ使用されています。

4

3 に答える 3

5

特にあなたの問題を考慮して、私は間違いなくイテレータを使用します(ベクトルのサブセットで作業します):

template<class Iterator>
int bar(Iterator begin, Iterator end)
{
    for (auto it = begin; it != end; ++it)
        (*it)++;
    return 0;
}

コンテナから抽象化するだけでなく、特定の範囲をシミュレートするために、従来の「開始」および「終了」イテレータとは異なるイテレータを簡単に渡すこともできます。

bar(a.begin() + 2, a.begin() + 4);

たとえば、上記のコードでは、1 から 4 までの要素にアクセスします (どちらも除外されます)。そして、これがライブの例です

于 2014-02-11T17:01:01.170 に答える
1

コンテナーが必要ない場合は、コンテナーを使用しないでください。反復可能な範囲を使用します。

コンテナーは反復可能な範囲であり、その内容の所有者でもあります。

a の場合vector、連続する iterable 範囲とコンテンツの所有者です。可能性としては、実装コードで がランダム アクセスの反復可能な範囲であるかどうかを知る必要があるだけです。

ただし、任意の連続した iterable 範囲を処理するには、実装をテンプレート ヘッダー ファイルに配置するか、高価な型の消去を行う必要があるという点でコストがかかります。これにアプローチする 2 つの方法は、 a の部分範囲のみを受け入れるvectorという事実を使用するか、連続した範囲の部分範囲のみを受け入れるという事実を使用することです。

私は連続した範囲のアイデアが好きです:

template<typename T>
struct contiguous_range {
  T* b; T* e;
  contiguous_range( contiguous_range const& ) = default;
  contiguous_range():b(nullptr), e(nullptr) {};
  contiguous_range& operator=( contiguous_range const& ) = default;
  std::size_t size() const { return e-b; }
  T* begin() const { return b; } // note, T*
  T* end() const { return e; } // note, T*
  template<typename U, typename=typename std::enable_if<
    sizeof(U)==sizeof(T)
    && std::is_convertible<U*, T*>::value
  >::type>
  contiguous_range( contiguous_range<U> const& o ):b(o.b), e(o.e) {};
  T& operator[]( std::size_t i ) const { return b[i]; }

  template<typename A>
  contiguous_range( std::vector<T, A> const& v ):b(v.data()), e(v.data()+v.size()) {}
  template<typename U, std::size_t N, typename=typename std::enable_if<
    sizeof(U)==sizeof(T)
    && std::is_convertible<U*, T*>::value
  >::type>
  contiguous_range( std::array<U, N> const& a ):b(a.data()), e(a.data()+a.size()) {}
  template<typename U, std::size_t N, typename=typename std::enable_if<
    sizeof(U)==sizeof(T)
    && std::is_convertible<U*, T*>::value
  >::type>
  contiguous_range( U(&a)[N] ):b(&a[0]), e((&a[0])+N) {}

  template<typename U, typename=typename std::enable_if<
    sizeof(U)==sizeof(T)
    && std::is_convertible<U*, T*>::value
  >::type>
  contiguous_range( U* b_, U* e_ ):b(b_), e(e_) {}
};

template<typename I>
auto contiguous_subrange( I b, I e )
-> contiguous_range<std::iterator_traits<I>::value_type>
{
  return {&*b, &*e};
}
template<typename C>
auto contiguous_subrange( C&& c, std::size_t start, std::size_t end )
-> decltype( contiguous_subrange( &c[start], &c[end] ) )
  { return ( contiguous_subrange( &c[start], &c[end] ) ) };

これで、関数は単純にcontiguous_range<int>orを取るcontinguos_range<const int>ことができ、暗黙的に を渡すことができますstd::vector<int>

std::vector等しく連続する部分範囲を設定することもできます。

a は a に対応し、 a は aconstiguous_range<int>に対応することに注意してください。std::vector<int>&contiguous_range<const int>std::vector<int> const&

于 2014-02-11T20:10:36.047 に答える