While striving for const-correctness, I often find myself writing code such as this
class Bar;
class Foo {
public:
const Bar* bar() const { /* code that gets a Bar somewhere */ }
Bar* bar() {
return const_cast< Bar* >(
static_cast< const Foo* >(this)->bar());
}
};
for lots of methods like bar()
. Writing these non-const methods which call the const ones by hand is tedious; besides, I feel I am repeating myself – which makes me feel bad.
What can I do to alleviate this task? (Macros and code generators are not allowed.)
Edit: Besides litb's solution I also like my own. :)
Casting away const relies on the caller only using the function on non-const objects. A potential solution is to alter the code in // .... so that it doesn't need to use the object's "current color". Add versions of all the functions you use, that take a QColor parameter instead.
const function use cases A const function can be called by either a const or non- const object. Only a non- const object can call a non- const function; a const object cannot call it.
const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.
Yes, in the sense that it can be const_cast away, or the object can have mutable members.
Another way could be to write a template that calls the function (using CRTP) and inherit from it.
template<typename D>
struct const_forward {
protected:
// forbid deletion through a base-class ptr
~const_forward() { }
template<typename R, R const*(D::*pf)()const>
R *use_const() {
return const_cast<R *>( (static_cast<D const*>(this)->*pf)() );
}
template<typename R, R const&(D::*pf)()const>
R &use_const() {
return const_cast<R &>( (static_cast<D const*>(this)->*pf)() );
}
};
class Bar;
class Foo : public const_forward<Foo> {
public:
const Bar* bar() const { /* code that gets a Bar somewhere */ }
Bar* bar() { return use_const<Bar, &Foo::bar>(); }
};
Note that the call has no performance lost: Since the member pointer is passed as a template parameter, the call can be inlined as usual.
Use following trick:
class Bar;
class Foo {
public:
Bar* bar() {
// non-const case
/* code that does something */
}
const Bar* bar() const {
return This().bar(); // use non-const case
}
private:
//trick: const method returns non-const reference
Foo & This() const { return const_cast<Foo &>(*this); }
};
Note it is possible to use unique function This
for any const/non-const functions.
Alternative solution without static_cast (but I prefer the first one):
class Bar;
class Foo {
public:
const Bar* bar() const { /* code that does something */ }
Bar* bar() { return const_cast<Bar*>(cthis().bar()); } // use const case
private:
const Foo & cthis() const { return *this; }
};
You can do something like this:
class Bar;
class Foo {
public:
const Bar* bar() const { return getBar(); }
Bar* bar() {
return getBar();
}
private:
Bar* getBar() const {/* Actual code */ return NULL;}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With