c++legacy-codeconst-castconst-pointer

Is it necessarily bad to use const_cast when working with legacy libraries?


I am writing a C++ program for Linux. I use many low-level libraries such as XLib, FontConfig, Xft etc. They are all written in pure C, and in some places in my code I have this annoying problem:

I wrap C structures in RAII-friendly classes, where resources are allocated in constructors and freed in destructors. Freeing most of these resources is not just calling free(), special library functions should be used instead (::XftFontClose(), ::FcPatternDestroy() etc), so I don't see benefits of using smart pointers. Instead, I keep read-only raw pointers to library resources inside my classes and provide getter functions returning constant pointers to these resources so that they are unable to be modified outside of the classes that own them.

For example, I have a class containing a sorted list of system fonts, and I can ask this class to find and open the best font that can be used to draw a specific character:

const ::XftFont* FontHandler::findBestFont(wchar_t character);

The callers should not be able to modify the underlying object pointed to by the returned pointer, this is the task of the class' methods/destructor.

The problem is that, most of the functions I want to pass the returned pointer to look like this:

void
XftDrawStringUtf8
               (XftDraw         *d,
                XRenderColor    *color,
                XftFont         *font, // It is not const
                int             x,
                int             y,
                XftChar8        *string,
                int             len);

As you can see, even if the function does not need to change the data pointed to, the pointer is not const, and the only way to make it work is to use const_cast, which is never recommended, as far as I know.

This is just a single example, but there are many such issues in the real code.

I wonder, why are these legacy libraries built in such a way? Why don't they use const pointers when they actually should be const? And what is the best way to deal with such problems?


Solution

  • Is it necessarily bad to use const_cast when working with legacy libraries?

    No.

    It's generally bad to design code that requires a lot of const_cast, because it suggests you haven't thought very carefully about mutability.

    You're using libraries that were written before const-correctness was much considered, and their design shortfalls are not your fault. Adapting to them is an entirely appropriate use of const_cast.

    Freeing most of these resources is not just calling free(), special library functions should be used instead(::XftFontClose(), ::FcPatternDestroy() etc.,) so I don't see benefits of using smart pointers

    You know you can use smart pointers with custom deleters, right? The benefit - that you don't have to implement five special methods in each class - is still there.

    At most, consider writing a rule-of-zero wrapper type storing a std::unique_ptr (or std::shared_ptr, or whatever) with a custom deleter. It's a lot less typing, and way fewer opportunities for annoying bugs.