0

要素の順序を無視して、2 つの std::pair 項目とそれらの等価性をテストする簡単なユーティリティ ファンクターを作成しようとしました。さらに (ここで問題が発生します)、これらの std::pair アイテムのコンテナーを取得し、コンテナー内の特定のペア引数のメンバーシップをテストする関数を作成しました。

/* A quick functor way to check the identity of the two items of a pair to see if each pair contains the same items regardless of order */
template <class T>
class EqualPairs : public std::binary_function<T,T,bool> {
  T arg2;

  public:
  explicit EqualPairs (const T& x) : arg2(x) { }

  bool operator() (const T& arg1) { 
    bool same = false;
    if (arg1 == arg2 || (arg1.first == arg2.second && arg1.second == arg2.first))
      same = true;
    return same;
  }
};

/* checks to see if the give pair p is a member of the list of pairs l. The pairs are compared disregarding the order of the pair elements (i.e. (4,2) == (2,4)) */
template <class P>
bool PairListMember (const P& p, const std::vector<P>& l)
{
  std::vector<P>::iterator it;
  it = find_if (l.begin(), l.end(), EqualPairs<P>(p));
  bool member_of_list = (it != l.end()) ? true : false;
  return member_of_list;
}

ジェネリック コンテナーの選択を許可するクリーンな方法が思いつかなかったので、現時点では std::vector をコンテナー タイプとしてハードコーディングしました。コンテナー タイプをジェネリックにするためのヘルプもいただければ幸いですが、今のところ、上記をコンパイルして動作させたいと思います。私が得るエラーは次のとおりです。

In function ‘bool PairListMember(const P&, const std::vector<P, std::allocator<_CharT> >&)’:

    error: expected `;' before ‘it’
    error: ‘it’ was not declared in this scope

In function ‘bool PairListMember(const P&, const std::vector<P, std::allocator<_CharT> >&) [with P = std::pair<int, int>]’:

    error: dependent-name ‘std::vector<P,std::allocator<_CharT> >::iterator’ is parsed as a non-type, but instantiation yields a type
    note: say ‘typename std::vector<P,std::allocator<_CharT> >::iterator’ if a type is meant

提案されているように「typename」を追加してコードを変更すると、次のエラーが発生するだけです。

error: no match for ‘operator=’ in ‘it = std::find_if [with _InputIterator = __gnu_cxx::__normal_iterator<const std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _Predicate = EqualPairs<std::pair<int, int> >](((const std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >*)l)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), ((const std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >*)l)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), EqualPairs<std::pair<int, int> >(((const std::pair<int, int>&)((const std::pair<int, int>*)p))))’

/usr/include/c++/4.2/bits/stl_iterator.h:637: note: candidates are: __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >& __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >::operator=(const __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >&)
4

2 に答える 2

5

コンパイラ エラーの場合は、typenameキーワードを使用する必要があります。

typename std::vector<P>::iterator it;

iterator型名です。つまり、std::vector 内に埋め込まれた型を参照します。テンプレート内で演算子を使用して typename にアクセスする場合::は、 typename キーワードを使用して、クラス内の変数または関数の名前ではなく、型の名前であることをコンパイラが認識できるようにする必要があります。

編集:const_iteratorまた、この場合はベクトルが const であるため、a を使用する必要があります。

typename std::vector<P>::const_iterator it;
于 2009-11-20T23:05:46.250 に答える
3

EqualPairsテンプレートにはいくつかの問題があります。これは binary_function から派生しますが、引数が 1 つしかないbinary_functionため、実際には ではありません。オブジェクトを変更しないため、const をoperator()作成できます (作成する必要があります) 。operator()EqualPairs

ある程度簡略化できると思います。

template<class T>
struct EqualPairs : public std::binary_function<T, T, bool>
{
    bool operator()(const T& lhs, const T& rhs) const
    {
        return lhs == rhs || lhs.first == rhs.second && lhs.second == rhs.first;
    }
};

次に、std::bind1st(またはstd::bind2nd) を使用して、バイナリ関数と入力パラメーターから述語を作成できます。また、関数を「ワンライナー」にすることで、実際には反復子の一時変数を宣言する必要がないため、取得consttypename修正は問題になりません。

template <class P>
bool PairListMember (const P& p, const std::vector<P>& l)
{
    return l.end() != std::find_if(l.begin(), l.end(), std::bind1st(EqualPairs<P>(), p));
}

テンプレート パラメーターとしてイテレーター型を使用することで、このテンプレートをより汎用的にすることができます。これにより、 への依存が削除されますstd::vector

template <class Iter>
bool PairListMember(const typename std::iterator_traits<Iter>::value_type& p, Iter first, Iter last)
{
    return last != std::find_if(first, last, std::bind1st(EqualPairs<typename std::iterator_traits<Iter>::value_type>(), p));
}
于 2009-11-21T00:03:01.707 に答える