-1

Not certain how I am to interprete the above.

no match for 'operator!=' in 'this != rhs'| Error| invalid initialization of non-const reference of type 'Collection&' from an rvalue of type 'Collection* {aka Collection*}'|

I have two methods where one calls another. However,when I run the code, as is, I get the error messages above.

Collection&  Collection::operator=(const Collection&& rhs)
        {
                   if (this!= rhs)// <--- Error |no match for 'operator!=' in 'this != rhs'
                    {
                        return copy(rhs);//<---Error| invalid initialization of non-const reference of type 'Collection&' from an rvalue of type 'Collection* {aka Collection*}'
                    }
                    return *this;
         }

Collection& Collection::copy(const Collection& coll)
{

}
Kobojunkie
  • 6,375
  • 31
  • 109
  • 164
  • `this` has type `Collection*`, which is not comparable with `Collection&&` – jpm Apr 26 '12 at 16:59
  • `this` is a pointer, while `rhs` is not. So you'll need a specific `operator!=` to handle that if you want. Or, just compare `this` to the address of the `rhs`. – Mr Lister Apr 26 '12 at 17:00
  • I'm new to move semantics, but wouldn't `this != &rhs` still work? – jpm Apr 26 '12 at 17:01
  • You will also need to have `copy` return something for the `return copy(rhs);` to compile. – smocking Apr 26 '12 at 17:02
  • @DeadMG Can you point me to an explanation of why not? – jpm Apr 26 '12 at 17:03
  • By the way, if this is supposed to be your basic, no frills `operator=` implementation, are you sure you wanted to write `Collection&&` and not `Collection&`? – Mr Lister Apr 26 '12 at 17:06
  • @jpm: Because the rvalue is `const`- it's junk. Fundamentally, he's written a function which can never, ever, be useful. – Puppy Apr 26 '12 at 17:07

3 Answers3

2

Assuming you have defined operator!=, you'll want to say if (*this != rhs). You need to dereference the this pointer if you are looking to check for whether their values are equal. Otherwise, if you are looking to see if they are the exact same object (likely in this case), then you want to take the address of rhs with this != &rhs. This solution does not require any operator overloading because you are just comparing two pointers, which is already supported for any type of pointer.

David Stone
  • 26,872
  • 14
  • 68
  • 84
2

Self-assignment checks are no longer considered idiomatic C++. It is generally inferior to copy-and-swap. The idiomatic assignment operator is this:

Collection& Collection::operator=(Collection rhs) {
    swap(rhs);
    return *this;
}

This assumes that you have defined copy and move constructors and a swap function. In addition, a move-semantics enabled class should take a non-const rvalue reference. The entire purpose of rvalue references is to mutate the rvalue- a const rvalue is worthless. Here's a simple example, where I use a heap-allocated int as the example resource.

class Collection {
    int* ptr; // example resource
public:
    Collection(const Collection& c) {
        ptr = new int(*c.ptr); // copy
    }
    Collection(Collection&& c) {
        ptr = c.ptr; // move
        c.ptr = nullptr;
    }
    void swap(Collection& rhs) {
        std::swap(ptr, rhs.ptr); // swap
    }
    Collection& operator=(Collection rhs) {
        swap(rhs);
        return *this;
    }
    ~Collection() {
        delete ptr; // rule of three, bitch
    }
};
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • I really should have mentioned copy-and-swap in my answer. I was thinking about it, but for some reason didn't say it. +1 – David Stone Apr 26 '12 at 17:22
  • Explanation for why that works: http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom – David Stone Apr 26 '12 at 17:25
  • So the arg to `operator=` is a temporary copy created via the copy ctor, and then it's data is just swapped in? And swap, here, is using move semantics? Is that right? – jpm Apr 26 '12 at 17:26
  • @jpm: `swap` does not use move semantics. It just swaps. The argument to `operator=` is copied or moved using the appropriate constructor as necessary. – Puppy Apr 26 '12 at 17:46
1

this is a Collection*, and rhs is const Collection&&. You can't != between them. You should convert rhs to a const Collection* via &rhs.

if (this!= &rhs)

Better yet, write an assignment operator where it doesn't matter if you try self assignment.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • That's not right. We don't want to dereference rhs, we want its address. – jpm Apr 26 '12 at 17:02
  • 2
    `rhs` is not a pointer and thus cannot be dereferenced, unless for some strange reason `operator*` was overloaded to return the address. You need to either dereference `*this` to check value equality or take the address of `rhs` with `&rhs` to determine memory equality. – David Stone Apr 26 '12 at 17:02