informa
3 min read
article

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.
// 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?

Latest Jobs

Studio Pixanoh LLC

Los Angeles, California
05.20.22
Combat Designer

Treyarch

Playa Vista, California or Vancouver, BC
05.20.22
AI Engineer

Question

Remote
05.20.22
Lead Level Designer (South Park)

Remedy Entertainment

Helsinki Metropolitan Area, Finland
05.23.22
Rigging Artist
More Jobs   

CONNECT WITH US

Register for a
Subscribe to
Follow us

Game Developer Account

Game Developer Newsletter

@gamedevdotcom

Register for a

Game Developer Account

Gain full access to resources (events, white paper, webinars, reports, etc)
Single sign-on to all Informa products

Register
Subscribe to

Game Developer Newsletter

Get daily Game Developer top stories every morning straight into your inbox

Subscribe
Follow us

@gamedevdotcom

Follow us @gamedevdotcom to stay up-to-date with the latest news & insider information about events & more