Vérification de l'appartenance à une liste à l'aide de la STL et une foncteur adaptée fonction unaire

StackOverflow https://stackoverflow.com/questions/1773757

Question

J'ai essayé d'écrire un bref foncteur utilitaire qui prend deux std :: éléments de paire et de tests pour l'égalité, mais sans tenir compte de l'ordre des éléments. De plus (et c'est là j'ai des ennuis) j'ai écrit une fonction pour prendre un conteneur de ces std :: éléments de paire et un test d'adhésion à un argument de paire donnée dans un conteneur.

/* 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;
}

Je ne pouvais pas penser à un moyen propre pour permettre la sélection de conteneur générique, donc je codé en dur un std :: vecteur comme type de récipient, pour l'instant. Aide à rendre générique le type de conteneur serait également apprécié, mais pour l'instant je voudrais simplement obtenir le plus récent pour compiler et travailler. L'erreur que je reçois est:

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

modifier le code en ajoutant un « typename », comme le suggère que les résultats dans les erreurs suivantes:

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> > > >&)
Était-ce utile?

La solution

Il y a quelques problèmes avec votre modèle de EqualPairs. Il dérive de binary_function mais n'est pas réellement un binary_function parce que operator() prend un argument. Vous pouvez (et devez) faire operator() const car il ne modifie pas l'objet EqualPairs.

Je pense que vous pouvez simplifier un peu.

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;
    }
};

Ensuite, vous pouvez utiliser std::bind1st (ou std::bind2nd) pour faire un prédicat de votre fonction binaire et le paramètre d'entrée. En outre, en faisant la fonction d'un « one liner » vous n'avez pas réellement besoin de déclarer une variable temporaire pour la iterator, ainsi obtenir const et typename correct est pas un problème.

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));
}

Vous pouvez faire ce modèle plus générique en prenant un type iterator comme paramètre de modèle. Cela supprime votre dépendance à l'égard 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));
}

Autres conseils

Pour votre erreur de compilation, vous devez utiliser le mot-clé typename.

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

iterator est un nomtype, à savoir il se réfère à un type intégré dans std :: vecteur. Lorsque vous accédez à un typename avec l'opérateur :: dans un modèle, vous devez utiliser le mot-clé typename de sorte que le compilateur sait qu'il est le nom d'un type, par opposition au nom d'une variable ou une fonction au sein de la classe.

Edit:. , vous avez besoin d'utiliser un const_iterator, parce que votre vecteur est const dans ce cas

typename std::vector<P>::const_iterator it;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top