1

If I try to compile:

class Outer 
{
    class Inner 
    {
        int t;
    };
public:
    Inner inner_;
    bool operator ==(Outer rightSide);
};

bool Outer::operator ==(Outer rightSide)
{
    if (inner_ == rightSide.inner_)
        return true;
    return false;
}

I get an error:

/home/martin/Projects/Experimentation/Various-build-desktop/../Various/main.cpp:18: 
error: no match for ‘operator==’ in ‘((Outer*)this)->Outer::inner_ == 
rightSide.Outer::inner_’

Please, is it just me doing something wrong or is this a property of C++

EDIT:

Oh, I never realized that the operator == is never synthesized, I was so convinced that it is synthesized, that I did not bother to check.
Thank you Parapura Rajkumar!

akuzma
  • 1,592
  • 6
  • 22
  • 49
Martin Drozdik
  • 12,742
  • 22
  • 81
  • 146
  • 8
    `==` is never automatically synthesized... why would inner classes be any exception – parapura rajkumar Jan 20 '12 at 15:41
  • 1
    First of all, it should simply `return inner_ == rightSide.inner_`, and secondly yes, it will not get synthesized for you, because its meaning is ambiguous. – Phonon Jan 20 '12 at 15:42
  • Why did you expect the compiler to give you implicit operators? Cf. this question http://stackoverflow.com/questions/217911/why-dont-c-compilers-define-operator-and-operator – Useless Jan 20 '12 at 15:45
  • Nothing to do with your question, but just a tip: pass the "rightSide" as const reference (const Outer& rightSide) for performance reasons. – Renan Greinert Jan 20 '12 at 15:50

2 Answers2

2

Comparison operators are never implicitly generated. Only these things are:

  • Default constructor,
  • Destructor,
  • Copy and move constructors,
  • Copy-assigment and move-assignment operators

If you want to be able to compare your types, you'll have to write your own comparison operators. If you implement them as members, then they should be declared const; otherwise, it will be impossible to compare constant objects. You might also consider taking arguments as constant references to avoid unnecessary copying; it makes little difference for simple types like these, but can be much more efficient for large or complicated classes. Something like:

bool Outer::operator==(Outer const & rhs) const {
    return inner_.t == rhs.inner_.t;
}

or as a non-member function:

bool operator==(Outer const & lhs, Outer const & rhs) {
    return lhs.inner_.t == rhs.inner_.t;
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • @phresndl destructors are always generated – codekiddy Jan 20 '12 at 15:59
  • @codekiddy: I was listing all the the things that can be implicitly generated; destructors certainly belong in that list. – Mike Seymour Jan 20 '12 at 16:01
  • 1
    What about the address-of `operator&()`? ... and the sequence `operator,()`? Sure, typically we don't think of them as being synthesized but they can be overloaded for a class (it is typically a Bad Idea but sometimes just what you need). – Dietmar Kühl Jan 20 '12 at 17:39
1

You didn't define the operator== for class Inner. So your code should be :

class Outer
{
    class Inner
    {
        int t;
    public:
        bool operator == (Inner inner)
        {
            return t == inner.t;
        }
    };
public:
    Inner inner_;
    bool operator == (Outer rightSide);
};

bool Outer::operator == (Outer rightSide)
{
    return inner_ == rightSide.inner_;
}
xucheng
  • 275
  • 6
  • 15
  • Actually, this is **not** how the operators _should_ look but how they _could_ look! To get how the _should_ look you want to make them non-members and probably take `const&` parameters. The former to support symmetric conversions, the latter for performance and to be applicable to a `const` left hand argument. – Dietmar Kühl Jan 20 '12 at 17:43