1

I have two files:

my_header.h:

class my_class {
public:
    my_class();

    my_class(long long number);

    my_class(int number);

    my_class(double number);

    bool operator<(const my_class& rhs) const;

    //////
}

my_class.h:

my_class::my_class()
{
    //implementation
}

my_class::my_class(long long number)
{
    //implementation
}

my_class::my_class(int number)
{
    //implementation
}

my_class::my_class(double number)
{
    //implementation
}

bool my_class::operator<(my_class const& rhs) const
{
    //implementation
}

I do not understand, where I do mistake. I overload operator <. Also, I have constructor from double type.

Of course, Also, I implement other 5 operators (==, !=, >, <=, =>) by this scheme. Other operators are in the same namespace, but they are not member function.

Test case is:

my_class a = 2;
bool check = 5.17 < long_int1;
Denis
  • 3,376
  • 10
  • 46
  • 68
  • 1
    Provide a free function `bool operator – clcto Nov 05 '14 at 22:30
  • possible duplicate of [Operator overloading : member function vs. non-member function?](http://stackoverflow.com/questions/4622330/operator-overloading-member-function-vs-non-member-function) – Alan Stokes Nov 05 '14 at 22:31
  • clcto, why I have to provide this function? In fact, I have double constructor, why c++ does not cast double -> my_class? – Denis Nov 05 '14 at 22:31
  • @Denis see the link in the linked question: http://www.csse.monash.edu.au/~jonmc/CSE2305/Topics/10.19.OpOverload/html/text.html#a_slight_problem_of_ordering It is just the way it is parsed, the standard probably defines this – clcto Nov 05 '14 at 22:34
  • @AlanStokes, I tried this - http://stackoverflow.com/a/4622467/1756750 It does not work. – Denis Nov 05 '14 at 22:46

2 Answers2

1

The rules of C++ forbid the use of implicit conversions to create an object on which to call a member function. For this reason, when an object supports implicit conversions, it is usual to define an binary operators as non-members (friend if necessary). For the comparison operators, I have a simple template base class which will provide them, provided my class has a member function compare, and inherits from it.

template <typename T>
class ComparisonOperators
{
    friend bool operator==( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) == 0;
    }
    friend bool operator!=( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) != 0;
    }
    friend bool operator<( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) < 0;
    }
    //  and so on.
};

You write this once, and then all you have to do is provide one (member) function, and derive from it:

class MyClass : public ComparisonOperators<MyClass>
{
public:
    int compare( MyClass const& other ) const
    {
        //  return <, == or > 0, according to whether this is
        //  <, == or > other.
    }
}
James Kanze
  • 142,482
  • 15
  • 169
  • 310
  • am I right, that in MyClass::compare function I have to compute `diff` between `(*this)` and `other`, and then I have to compare `diff` and `0`? – Denis Nov 05 '14 at 23:49
  • @Denis You have to do whatever is necessary to be able to return an `int` with a value less than 0 if `*this` should be ordered before `other`, equal to 0 is `*this` should be considered equal to `other`, and greater than 0 if `*this` should be considered greater than `other`. What this means in practice will depend on the actual data types in your object, and how you want to define the relationships. – James Kanze Nov 06 '14 at 09:56
0

The problem is that the compiler has no way of knowing that you want to implicitly convert 5.17 to an instance of my_class. Think what would happen if you had two different classes that could accept a double as the only constructor argument. There are two ways of solving this.

  1. Provide a conversion operator. This will allow the compiler to read your instance of my_class as a double.
  2. Switch the order of the arguments. !(my_class > 5.17) should work fine.
Benjy Kessler
  • 6,552
  • 6
  • 32
  • 61