RL-S
RL-S

Reputation: 937

Violating const correctness: What problems should I expect realistically?

I want to use a function parser library where the member function FunctionParser::Eval() is non-const, because it writes an error code to a member variable. I would like to integrate this function parser into a codebase, where this function would get called through a const member function of a class holding that function parser, thus violating const correctness.

This const member function is part of an interface, where the constness makes semantic sense. I could change that interface, so that remains an option. As a test, I used const_cast to execute the code violating const correctness, which did not cause any errors or failed unit tests (at least not in Debug mode).

Now my question is: What problems down the road should I expect when violating const correctness in this case? (And would that ever be worth it?)

Upvotes: 2

Views: 179

Answers (3)

R Sahu
R Sahu

Reputation: 206577

What problems down the road should I expect when violating const correctness in this case? (And would that ever be worth it?)

If the object in question was constructed as a const object, then you definitely run into undefined behavior. However, if the object was constructed as a non-const object, then using const_cast to call a non-const member function is OK.

Simple example:

struct Foo {int f; };

void testFoo(Foo const& foo)
{
   const_cast<Foo&>(foo).f = 10; // Analogous to calling a non-const member function.
}

int main()
{
    Foo obj1 = {20};
    Foo const obj2 = {30};

    testFoo(obj1); // ok. obj1 was constructed as a non-const object.
    testFoo(obj2); // Not ok.  obj2 was constructed as a non-const object.
}

Upvotes: 1

Asteroids With Wings
Asteroids With Wings

Reputation: 17454

You're not violating const-correctness; you're merely bypassing the built-in language checks for it.

Modifying a non-const thing is fine, even if you had to cast away some constness somewhere along the way (indeed, this is what const_cast is for).

This is generally considered to be a dangerous thing to do, though, and dangerous code to write, so you should modify your interface or design. (This sounds like a good use case for mutable.)

But what runtime errors or weirdness can you expect right now? None at all.

Upvotes: 1

cdhowie
cdhowie

Reputation: 168988

If the object is actually defined const, then casting away const-ness to modify the object is undefined behavior.

Consider instead using the mutable keyword, which declares an exception to const-ness for a given field; a mutable field is always non-const even when accessed on an object that is considered const in the current context (including from within const methods).

class foo {
private:
    int a;         // cannot be modified on a const foo
    mutable int b; // CAN be modified on a const foo!
};

You could use the mutable keyword for fields related to error tracking.

Of course, a better pattern would be to throw an error object if an error occurs. If your API design does not permit this, making the relevant fields mutable is the correct workaround.

Upvotes: 8

Related Questions