57 votes

Comment vérifier si l'opérateur == existe?

Je suis en train de créer un exemple, qui permettrait de vérifier l'existence de l' operator== (membre ou non-membre de la fonction). Pour vérifier si une classe a un membre de l' operator== est facile, mais comment faire pour vérifier si il est un non-membre de l' operator==?

C'est ce que j'ai à présent :

#include <iostream>

struct A
{
    int  a;

    #if 0
    bool operator==( const A& rhs ) const
    {
        return ( a==rhs.a);
    }
    #endif
};
#if 1
bool operator==( const A &l,const A &r )
{
    return ( l.a==r.a);
}
#endif


template < typename T >
struct opEqualExists
{
    struct yes{ char a[1]; };
    struct no { char a[2]; };

    template <typename C> static yes test( typeof(&C::operator==) );
    //template <typename C> static yes test( ???? );
    template <typename C> static no test(...);

    enum { value = (sizeof(test<T>(0)) == sizeof(yes)) };
};

int main()
{
    std::cout<<(int)opEqualExists<A>::value<<std::endl;
}

Est-il possible d'écrire une fonction de test pour tester l'existence de la non-membre de l' operator==? Si oui, comment?

btw, j'ai vérifié sur des questions similaires, mais je n'ai pas trouvé une bonne solution :
Est-il possible d'utiliser SFINAE/modèles de vérifier si un opérateur n'existe?

C'est ce que j'ai essayé :

template <typename C> static yes test( const C*,bool(*)(const C&,constC&) = &operator== );

mais la compilation échoue si la non-membre de l'opérateur== est supprimé

46voto

iammilind Points 29275

Le tour suivant fonctionne. Et il peut être utilisé pour tous ces opérateurs:

 namespace CHECK  // namespace to let "operator ==" not become global
{
  typedef char no[7];
  template<typename T> no& operator == (const T&, const T&);

  template <typename T>
  struct opEqualExists // *(T*)(0) can be replaced by *new T[1] also
  {
    enum { value = (sizeof(*(T*)(0) == *(T*)(0)) != sizeof(no)) };
  };
}
 

Usage:

 std::cout<<CHECK::opEqualExists<A>::value<<std::endl;
 

Voir la démo ici .

16voto

jopasserat Points 2839

Regarder du coup de pouce du Concept de Bibliothèque (BCCL) http://www.boost.org/doc/libs/1_46_1/libs/concept_check/concept_check.htm.

Il vous permet d'écrire des exigences qu'une classe doit correspondre pour que le programme à compiler. Vous êtes relativement libre avec ce que vous pouvez vérifier. Par exemple, la vérification de la présence d' operator== d'une classe Foo voudrais écrire comme suit:

#include <boost/concept_check.hpp>


template <class T>
struct opEqualExists;

class Foo {
public:
    bool operator==(const Foo& f) {
       return true;
    }

   bool operator!=(const Foo& f) {
      return !(*this == f);
   }

   // friend bool operator==(const Foo&, const Foo&);
   // friend bool operator!=(const Foo&, const Foo&);
};

template <class T>
struct opEqualExists {
   T a;
   T b;

   // concept requirements  
   BOOST_CONCEPT_USAGE(opEqualExists) {
      a == b;
   }
};


/*
bool operator==(const Foo& a, const Foo& b) {
   return true; // or whatever
}
*/


/*
bool operator!=(const Foo& a, const Foo& b) {
   return ! (a == b); // or whatever
}
*/


int main() {
   // no need to declare foo for interface to be checked

   // declare that class Foo models the opEqualExists concept
   //   BOOST_CONCEPT_ASSERT((opEqualExists<Foo>));
   BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Foo>)); // need operator!= too
}

Ce code se compile très bien tant que l'un des deux implémentations de l' operator== est disponible.

Suivant @Matthieu M. et @Luc Touraille conseils, j'ai mis à jour l'extrait de code pour donner un exemple d' boost::EqualityComparable d'utilisation. Une fois de plus, veuillez noter que EqualityComparable vous oblige à déclarer operator!= trop.

3voto

histumness Points 473

Je sais que cette question a été répondue depuis longtemps, mais j’ai pensé qu’il pourrait être intéressant de noter pour ceux qui découvrent cette question à l’avenir que Boost vient d’ajouter une série de traits "has operator" à leur bibliothèque type_traits, et parmi eux has_equal_to , qui fait ce que OP demandait.

0voto

BЈовић Points 28674

Juste pour référence, je montre comment j'ai résolu mon problème, sans qu'il soit nécessaire de vérifier si le operator== existe:

 #include <iostream>
#include <cstring>

struct A
{
    int  a;
    char b;

    #if 0
    bool operator==( const A& r ) const
    {
        std::cout<<"calling member function"<<std::endl;

        return ( ( a==r.a ) && ( b==r.b ) );
    }
    #endif
};
#if 1
bool operator==( const A &l,const A &r )
{
    std::cout<<"calling NON-member function"<<std::endl;
    return ( ( l.a==r.a ) &&( l.b==r.b ) );
}
#endif

namespace details
{
struct anyType
{
    template < class S >
    anyType( const S &s ) :
        p(&s),
        sz(sizeof(s))
    {
    }

    const void *p;
    int sz;
};
bool operator==( const anyType &l, const anyType &r )
{
    std::cout<<"anyType::operator=="<<std::endl;
    return ( 0 == std::memcmp( l.p, r.p, l.sz ) );
}
} // namespace details

int main()
{
    A a1;
    a1.a=3;a1.b=0x12;
    A a2;
    a2.a=3;a2.b=0x12;

    using details::operator==;

    std::cout<< std::boolalpha << "numbers are equals : " << ( a1 == a2 ) <<std::endl;
}
 

0voto

sarat Points 2337

OMI, cela doit faire partie de la classe elle-même qu'il traite avec le secteur privé des attributs de la classe. Les modèles sont interprétées au moment de la compilation. Par défaut, il génère de l'opérateur==,constructeur, destructeur et le constructeur de copie qui ne peu-sage de copier (copie) ou bit à bit des comparaisons de l'objet de même type. Les cas particuliers (les différents types) doit être surchargé. Si vous utilisez l'opérateur global de la fonction, vous aurez à déclarer la fonction en tant qu'ami pour accéder à la partie privée ou autre chose que vous avez à exposer les interfaces requises. Parfois, c'est vraiment moche ce qui peut provoquer une inutile d'exposer d'une fonction.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X