What is the best way to deal with a library that has not marked any functions const?

c++, constants

Solution

How easy is it to tell whether the functions in the library actually modify anything or not?

If it's easy to tell, and they don't, then you can `const_cast` your const pointer/reference to non-const and call the library function. You might want to throw a wrapper around the library classes to do this for you, which is tedious and verbose but gets that code out of your classes. This wrapper could perhaps be a subclass that adds some const accessors, depending whether the way you use the library class allows that to work.

If it's hard to tell, or they do modify things, then you need to use non-const instances and references to the library classes in your code. `mutable` can help with those of type (2), but for those of type (1) you just need to pass non-const arguments around.

For an example of why it might be hard, consider that the library author might have written something like this:

struct Foo {
    size_t times_accessed;
    int value;
    int get() {
        ++times_accessed;
        return value;
    }
};

Now, if you `const_cast` a `const` instance of `Foo` and call `get()`, you have undefined behavior[*]. So you have to be sure that `get` really doesn't modify the object it's called on. You could mitigate this a bit, by making sure that you never create any const instances of `Foo`, even though you do take const references to non-const instances. That way, when you `const_cast` and call `get` you at least don't cause UB. It might make your code confusing, that fields keep changing on objects that your functions claim not to modify.

[*] Why is it undefined behavior? It has to be, in order that the language can guarantee that the value of a `const` object never changes in a valid program. This guarantee allows the compiler to do useful things. For example it can put `static const` objects in read-only data sections, and it can optimize code using known values. It also means that a `const` integer object with a visible initializer is a compile-time constant, which the standard makes use of to let you use it as the size of an array, or a template argument. If it wasn't UB to modify a const object, then const objects wouldn't be constant, and these things wouldn't be possible:

#include <iostream>

struct Foo {
    int a;
    Foo(int a) : a(a) {}
};

void nobody_knows_what_this_does1(const int *p); // defined in another TU
void nobody_knows_what_this_does2(const int *p); // defined in another TU

int main() {
    const Foo f(1);
    Foo g(1);
    nobody_knows_what_this_does1(&f.a);
    nobody_knows_what_this_does2(&g.a);
    int x;
    if (std::cin >> x) {
        std::cout << (x / f.a); // Optimization opportunity!
        std::cout << (x / g.a); // Cannot optimize!
    }
}

Because `f` is a const object, and hence `f.a` is a const object, the optimizer knows that `f.a` has value 1 when it's used at the end of the function. It could, if it chose, optimize away the division. It doesn't know the same thing about `g.a`: `g` is not a const object, a pointer to it has been passed into unknown code, so its value might have changed. So if you're the author of `nobody_knows_what_this_does1` or `nobody_knows_what_this_does2`, and you're thinking of `const_cast`ing `p` and using it to modify its referand, then you can only do it if you somehow know that the referand is non-const. Which normally you don't, so normally you don't use `const_cast`.

Problem

I am trying to implement the use of a C++ library within my project that has not used const modifiers on its access functions. Up until now I have been using const in all of my code but this new library is causing two main problems: Functions where the arguments are passed as const references cannot use the argument's access functions if these arguments are of a type defined by the library. Classes with member objects of types defined by the library cannot use the access functions of these objects within a const function. What is the best way to overcome this issue? The easiest solution would be to simply remove all use of const from my code but that would be quite frustrating to do. Additional info: In this case I do have access to the source code and can see that the access functions do not modify anything. I omitted this information as I was interested in the more general case as well. For my scenario, `const_cast` appears to be the way to go PS The library writer is not evil! It is more a bit of rough and ready code that he has kindly open sourced. I could ditch the library and use something more professional as others have noted. However, for this small time-constrained project, the simplicity of the interface to this library has made it the best choice.

Original source