Feed Icon RSS 1.0 XML Feed available

When should one use const_cast, anyway?

Date: 12-Jun-2010/23:35

Tags:

Characters: (none)

I saw a question on StackOverflow asking about why one would use const_cast. Because I've thought about that question lately I glossed over that they were asking specifically about applications of casting away volatile...which I didn't even know you could use const_cast to do!
So I learned something. But I thought the answer I wrote to why you would use const_cast at all was pretty decent, so I was going to leave it there. But then I decided it was too off topic so I'd move it here.
The most common use of const_cast I've seen (with const) is this scenario:
  • You're calling a library that has something like a printFoo(Foo* fooPointer) function, which clearly requires a non-const Foo.
  • There's good reason to be "sure" this function doesn't modify the Foo, but you're unable to change the prototype or the source to express that knowledge for some reason.
  • Your code has made an effort to only use Foo* in contexts where writability is needed and const Foo* in all other contexts.
...that means that as a stopgap measure, you'll have to const_cast in order to cross this divide and call the routine.
OTOH, the most legitimate use I know of is in subsystems that own objects in a non-const sense, yet have cases where they hand back const pointers to callers. The subsystem natively has more privileges on those objects, so if a caller passes one of those const pointers back it can "upgrade" the privileges.
Sure, the subsystem could store a useless map from non-const pointers to const ones...but const_cast is more time and space efficient:
const SubsystemObject* Subsystem::getReadOnlyObjectById(int id) {
     SubsystemObject* subsystemObject = getObjectCore(id);

#ifdef WORLD_WITHOUT_CONST_CAST
     constMap[subsystemObject] = subsystemObject;
#endif

     return subsystemObject;
}

void Subsystem::someMethod(const SubsystemObject* constSubsystemObject) {
     SubsystemObject* subsystemObject;

#ifdef WORLD_WITHOUT_CONST_CAST
     subsystemObject = constMap[constSubsystemObject];
#else
     subsystemObject = const_cast<SubsystemObject*>(constSubsystemObject);
#endif

     doSomethingNeedingNonConstAccess(subsystemObject);
}
Business Card from SXSW
Copyright (c) 2007-2018 hostilefork.com

Project names and graphic designs are All Rights Reserved, unless otherwise noted. Software codebases are governed by licenses included in their distributions. Posts on blog.hostilefork.com are licensed under the Creative Commons BY-NC-SA 4.0 license, and may be excerpted or adapted under the terms of that license for noncommercial purposes.