While I was learning std::move
, I found a strange issue.
If I add only a destructor that do nothing to a perfect program, I will get a compile error.
#include <iostream>
using namespace std;
class M {
public:
int database = 0;
M &operator=(M &&other) {
this->database = other.database;
other.database = 0;
return *this;
}
M(M &&other) { *this = std::move(other); }
M(M &m) = default;
M() = default;
~M() { /* free db */ }
};
class B {
public:
M shouldMove;
//~B(){} //<--- ## Adding this line will cause compile error. ##
};
int main() {
B b;
B b2 = std::move(b); //## error at this line if the above line is added
return 0;
}
Live code: https://ideone.com/UTR9ob
The error is invalid initialization of non-const reference of type 'B&' from an rvalue of type 'std::remove_reference<B&>::type {aka B}'
.
Question:
- (1) Which rules of C++ syntax enforce that? In other words, what does the error mean?
- (2) If I want to add destructor that do almost nothing (e.g. only print debug log) to
B
, do I really have to follow the rule-of-five instead? If no, how to make it compile? Following the rule of five just because of that is too tedious and dirty in my opinion.
I think the rule of zero is just a good practice.
However, from this example, it seems to me that it is a hard rule that if violated, I will get compile error.