Sponsored By

Using Mutable To Write Better Container Code

In this post I take a look at how to use "mutable" in C++ while giving in to the urge to over-comment some code.

Neil Gower, Blogger

October 7, 2009

4 Min Read
Game Developer logo in a gray background | Game Developer

// Ever wondered what the keyword "mutable" is for? Been annoyed by duplicate
// functions while trying to write const-correct code? This might be what you
// need...
class MyContainer {
public:
    // Suppose we've got a container class that holds some objects...
    struct MyObject {};

private:
    // The objects could be stored in a regular array, like this.
    MyObject contents[10];

    // Or, you can declare the contents mutable. This means the array is never
    // treated as a const member, even if "this" is a const pointer (such as
    // inside a const member function)
    mutable MyObject mutableContents[10];

public:
    // For example, this lookup() method is declared const, and it is const
    // in the sense that it doesn't change the container. However, it returns
    // objects from the container as non-const, so the objects *can* be
    // changed...
    MyObject& lookup( size_t idx ) const {
        // Illegal! All members are treated as const in a const method, and
        // you can't convert from const to non-const to return it.
        //return contents[idx];

        // but mutable is okay...
        return mutableContents[idx];
    }
    // Does this violate what it means for the container to be const?
    //
    // That's up to you and the design of your class. Maybe it doesn't matter
    // to the const-ness of the container what the values of the objects are.
    // Usually however, we want to be more strict...

    // If you don't want the contents of a const container to be changeable,
    // you could implement the lookups as a pair of functions like
    // strictLookup(), below.
    MyObject& strictLookup( size_t idx ) {
        return lookup(idx);
    }

    // What's nice about this approach is that you don't have two copies of
    // the lookup code (which in this example is trivial, but wouldn't be in
    // a real container). Both the const and non-const versions of
    // strictLookup() can share lookup(), because it is a const method
    // accessing a mutable data member.
    //
    // BTW - A properly strict version of this class would also make lookup()
    //     private.
    const MyObject& strictLookup( size_t idx ) const {
        return lookup(idx);
    }

    // The catch with using mutable is that the compiler won't stop *you*
    // from changing the mutable members of your class inside your const
    // methods, which you probably don't want to do. So using mutable
    // requires some care.
    //
    // What about const_cast? Sadly, const_cast isn't guaranteed to work if
    // the container itself was declared const. For example, the compiler is
    // allowed to put a const container in a special read-only memory area
    // (if such a thing exists on your platform), which would cause
    // const_cast to fail at run-time. Proper uses of const_cast are few and
    // far between, and this isn't one of them.
};


// So to summarize...
int main( void ) {
    MyContainer c;
    // cc is just a reference to the container c, that treats it as const.
    const MyContainer& cc( c );

    // We can access container contents without restriction going through
    // lookup(), even though it is a const method...
    MyContainer::MyObject& a = c.lookup( 1 );
    MyContainer::MyObject& b = cc.lookup( 2 );

    // But using strictLookup(), we can't get a non-const object reference
    // out of a const container.
    MyContainer::MyObject& x = c.strictLookup( 3 );
    // illegal!
    //MyContainer::MyObject& y = cc.strictLookup( 4 );
    const MyContainer::MyObject& y = cc.strictLookup( 4 );

    return 0;
}

// Code with prose snippets, instead of prose with code snippets. Like it?
// Hate it? Wish the whole thing was in assembly?

Read more about:

Blogs

About the Author

Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like