I want to do method chaining on class Point below.
#include <iostream>
class Point {
public:
Point(int x, int y): _x(x), _y(y) {}
Point& moveX(int x);
Point& moveY(int y);
Point& print() const;
...
};
...
Point& Point::print() const {
std::cout << "(" << _x << "," << _y << ")" << std::endl;
return *this; // Compile fails
}
I think it makes sense to mark print() as const member function because it just print the internal members. However, I want to do method chaining among both non-const and const function like below.
int main() {
Point p(1,1);
p.moveX(10).print().moveY(11); // method chaining
}
So I have to return this as non-const but it fails the compilation because, in my understanding, the members are marked const including this in const member function.
Is there a way to do method chaining in this situation?
The reason why this fails is that inside a
constmember function,thisis really aconst Point*, not aPoint*. Thus you are trying to initialize a non-constreference from aconstpointer. It’s not that the compiler isn’t believing you, you’re just asking for two incompatible things at one time.This is one of the very few valid uses of
const_cast, in my opinion. Normally, usingconst_castis almost always a sign of a design error, or worse a programming error.Here, the function is really
constand should beconst, but there is no reason why you shouldn’t be able to chain something non-constafterwards, so it’s arguably legitimate to do such a thing.Do note, however, although the function is strictly
const(in respect to the object, not so much in its use of IO functions!), one thing you should consider is that in some (rare) cases, it may result in code that doesn’t do what you want. The compiler is allowed to cache the result of aconstfunction and omit another call to the sameconstfunction (since you promised that it won’t change anything). Therefore, it is allowable to optimizesome_point.Print().Print();intosome_point.Print(). This is probably not a problem for you (why would you want to print the same values twice), just something to be generally aware of.