How to determine if a class implements! = Operator overload?

Given the following function:

template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
  if (a.size() != b.size())
    return false;

  for (size_t i = 0; i < a.size(); ++i)
    if (a[i] != b[i]) // Requires that the != operator is supported by the template type.
      return false;

  return true;
}

How can I determine if a given T operator overrides !=? If someone uses the type without overloading, this can lead to a simple binary comparison, which can lead to incorrect results. Therefore, I want to be able to use only those classes that have their own operator overloading !=.

+4
source share
6 answers

, , , ! =, ( ) , , T, ! =. , :

1) if (a[i] != b[i]), , , != (, std::vector<sample2> marcinj), , std::equal. .

2) , ( , ). , , ( ), , Pixelchemist. , std:: equals .

, , :

template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
  if (a.size() != b.size())
    return false;

  for (size_t i = 0; i < a.size(); ++i)
    if (a[i] != b[i])
      return false;

  return true;
}

template <typename T>
static bool equals(const std::vector<T*> &a, const std::vector<T*> &b) {
  if (a.size() != b.size())
    return false;

  for (size_t i = 0; i < a.size(); ++i)
    if (*a[i] != *b[i])
      return false;

  return true;
}

1/2/3/4 marcinj. , (operator == (const sample1&)) .

, , .

+1

[update 1 - boost 'semi' solution]

, , ( , != ), , boost has_not_equal_to. , , . .

[ 2 - ]

:

#include <iostream>
#include <vector>

template<typename T>
concept bool OperatorNotEqual_comparable()
{
    return requires (T a, T b) {
        { a.operator!=(b) } -> bool;
    };   
}

template <OperatorNotEqual_comparable T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) {
  if (a.size() != b.size())
    return false;

  for (size_t i = 0; i < a.size(); ++i)
    if (a[i] != b[i]) // Requires that the != operator is supported by the template type.
      return false;

  return true;
}

struct sample1{
    bool operator!=(const sample1&) const { return true; }
};

struct sample2{
};

struct sample3{
    operator void*() { return 0; }
};

int main() {
    // Compiles ok!
    std::vector<sample1> vec1;
    equals(vec1, vec1);

    // Fails, which is OK!
    //std::vector<sample2> vec2;
    //equals(vec2, vec2);    

    // Fails, which is OK!
    //std::vector<sample2*> vec2;
    //equals(vec2, vec2);

    // Fails, which is OK!
    //std::vector<int> vec4;
    //equals(vec4, vec4);        

    // Fails, which is OK!
    //std::vector<sample3> vec5;
    //equals(vec5, vec5);            
}

http://melpon.org/wandbox/permlink/txliKPeMcStc6FhK

[ - SFINAE, ]

SFINAE ( gcc 6.0),

#include<iostream>
#include<string>
#include<type_traits>

template<typename T>
class has_not_equal{
    template<typename U>
    struct null_value{
        static U& value;
    };

    template<typename U>
    static std::true_type test(U*,decltype(null_value<U>::value!=null_value<U>::value)* = 0);
    static std::false_type test(void*);

public:
    typedef decltype(test(static_cast<T*>(0))) type;
    static const bool value = type::value;
};

struct sample1{
    bool operator!=(const sample1&) { return true; }
};

struct sample2{
};

int main(){
    std::cout<<std::boolalpha;
    std::cout<<has_not_equal<int>::value<<std::endl;
    std::cout<<has_not_equal<std::string>::value<<std::endl;

    std::cout<<has_not_equal<sample1>::value<<std::endl;
    std::cout<<has_not_equal<sample2>::value<<std::endl;
}

:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
true
true
true
false

, operator==, operator!=

+5

T operator !=, , (, ) . , T operator !=, . , T operator != .

+1

( ) ( ), ( operator!=) , T , , " ".

, , .

template <typename T>
static bool equals(const std::vector<T> &a, const std::vector<T> &b) 
{
  return std::equal(a.begin(), a.end(), b.begin());
}

template <typename T>
static bool equals(const std::vector<T *> &a, const std::vector<T *> &b) 
{
  return std::equal(a.begin(), a.end(), b.begin() 
    [](T* ap, T* bp) -> bool { return *ap == *bp; });
}
+1

, != ( ), (, marcinj):

#include <iostream>
#include <vector>
#include <type_traits>

template <class T, class = void>
struct has_not_equal: std::false_type { };

template <class T>
struct has_not_equal<T, typename std::enable_if<std::is_same<decltype(static_cast<bool (T::*)(const T&)const>(&T::operator!=)), bool (T::*)(const T&)const>::value>::type >: std::true_type { };

struct sample1{
    bool operator!=(const sample1&) const { return true; }
};
struct sample2{
};
struct sample3:sample2 {
  bool operator!=(const sample2& b) const { return true; }
};

struct sample4:sample2 {
  bool operator!=(const sample2& b) const { return true; }
  bool operator!=(const sample4& b) const { return true; }
};

int main(){

    std::cout<<std::boolalpha;
    std::cout<<has_not_equal<int>::value<<std::endl;
    std::cout<<has_not_equal<std::string>::value<<std::endl;

    std::cout<<has_not_equal<sample1>::value<<std::endl;
    std::cout<<has_not_equal<sample2>::value<<std::endl;
    std::cout<<has_not_equal<sample3>::value<<std::endl;
    std::cout<<has_not_equal<sample4>::value<<std::endl;
}

:

false
false
true
false
false
true

!= , has_not_equal...

+1

- , , .

In C ++, there is no such thing as a binary comparison. Either your class / structure has one operator!=, or the template will not be created (and if there are no other candidates, then this will be an error).

0
source

All Articles