I've been working for longer now with the 3ds max SDK, which in nearly all parts doesn't use const
at all. So even a Width()
or Height()
getter of a Bitmap
isn't marked as const
. This has been already a real annoyance in small projects, but since I've been working on a larger project, it becomes increasingly terrible.
For example, I am holding a single Bitmap
instance as a shared_ptr<Bitmap>
member in multiple class instances out of performance reasons. Of course there are cases I want to avoid by all means that a single instance may change the properties for all instances, thus all raw pointer getters (necessary for the SDK) deliver a const Bitmap*
. Unfortunately, now I can't even ask the const Bitmap*
for its width - because Width()
is non-const.
I'm asking myself what is the best way to deal with this. I see three options:
const_cast
at every place it's necessary. That will be at many places, and it's pretty bad to read.const
methods at least for the methods which are highly presumably safe. This would encapsulate all the const_cast
in one place and be also suitable for other projects.I have been warned (and I know) that this might be opinion-based. But I had to deal with this annoying problem for a long time now, and I'd really like to find a solution and thus need the experience of others.
First of all, I would like to mention that lack of const
correctness may be justifiable by implementation details, for example getter function may perform lock on internal synchronization primitive and therefore always alters internal state and can not be marked as const
:
int Bitmap::Width(void)
{
int width{};
::std::lock_guard<::std::mutex> const lock{m_sync};
width = m_width;
return width;
}
As a workaround you can write a dedicated PImpl bitmap wrapper restricting direct access to bitmap implementation forwarding functions of interest with appropriate const
qualifiers:
class SharedBitmap
{
private: ::std::shared_ptr<Bitmap> m_p_bitmap;
public: int Width(void) const
{
return m_p_bitmap->Width();
}
// other methods...
};
Note that this approach is different from third option listed in question as it does not involve const_cast
.