代码之家  ›  专栏  ›  技术社区  ›  Shamster

使用stl和一元函数自适应函数检查列表成员身份

  •  0
  • Shamster  · 技术社区  · 16 年前

    我尝试编写一个简短的实用函数,它接受两个std::pair项和测试以确保它们的相等性,但忽略了元素的顺序。另外(这也是我遇到问题的地方),我编写了一个函数来获取这些std::pair项的容器,并测试容器中给定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> > > >&)
    
    2 回复  |  直到 16 年前
        1
  •  3
  •   CB Bailey    16 年前

    您的 EqualPairs 模板。它从二进制函数派生,但实际上不是 binary_function 因为 operator() 只接受一个参数。你可以(也应该)做 运算符() 因为它不修改 等值线 对象。

    我认为你可以稍微简化一下。

    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 )从二进制函数和输入参数中生成谓词。另外,通过使函数成为一个“一行程序”,实际上不需要为迭代器声明临时变量,因此 const 和 typename 正确不是问题。

    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));
    }
    
        2
  •  5
  •   Charles Salvia    16 年前

    对于编译器错误,需要使用 typename 关键字。

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

    iterator 是一个类型名,即它引用了std::vector中的嵌入类型。当您使用 :: 运算符在模板中,需要使用type name关键字,以便编译器知道它是类型的名称,而不是类中某个变量或函数的名称。

    编辑: 另外,您需要使用 const_iterator ,因为在这种情况下向量是常量。

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