I ran into a case recently where I had a const member function performing an operation and returning a result. For example,
class Foo { ...
Foo add(Foo const & x) const;
}
But someone else was inadvertently calling it like it was updating the this
object (ignoring the result):
Foo a = ...;
Foo b = ...;
a.add(b);
(This bug was actually introduced by an imperfect refactoring.)
Is there a way to make the last line above trigger an error or a warning? The next best thing would be a run-time catch, which is mostly addressed by the following template. However, it kills the return value optimization, as seen by the counter result.
template<typename T>
class MustTake {
T & obj;
bool took;
public:
MustTake(T o) : obj(o), took(false) {}
~MustTake() { if (!took) throw "not taken"; }
operator T&() { took = true; return obj;}
};
struct Counter {
int n;
Counter() : n(0) {}
Counter(Counter const & c) : n(c.n+1) {}
~Counter() {}
};
Counter zero1() {
return Counter();
}
MustTake<Counter> zero2() {
return Counter();
}
int main() {
Counter c1 = zero1();
printf("%d\n",c1.n); // prints 0
Counter c2 = zero2();
printf("%d\n",c2.n); // prints 1
zero1(); // result ignored
zero2(); // throws
return 0;
}
I suppose I can ameliorate the inefficiency by using a macro so that MustTake<> is debug only and a no-op for release.
I am looking for a compile-time solution. Failing that, I am looking for the best run-time solution.