C++ – Naming Conventions for Non-const Getters

cobject-oriented

Quite often you need to define a getter returning a reference to a member, and a corresponding setter.

They usually look somewhat like this :

class Foo
{
    Type member;
public:
    const Type& getVar() const { return member; }
    void setVar(const Type & value) { member = value; }
}

However, sometimes you have to modify the Type object returned by getVar and need to get a non-const reference to it, so it is required to add another getter.

How do you call this additional method? I have never seen a "standard" way to write it. Is there a way to write it so that when anyone read the name, they understand it is a non-const getter ?

What I currently do is this :

Type & retrieveVar() { return member; }

I'm not sure it is explicit enough for the reader. How do you deal with this issue ?

Best Answer

As far as the C++ standard library is concerned, there are two distinct cases, based on the answer to one question: are you accessing an object or manipulating an object's property?

Accessing the contents of a container is accessing a conceptual subobject of the container. This is usually done via an overloaded function that returns a reference to the object. That reference will be const or non-const based on whether the container is const or not. This is true whether you're talking about std::get<tuple>, std::optional::value, or std::vector::at.

For manipulating properties of an object, this is typically done via return values/parameters. It's still using an overloaded function; one overload takes no parameters at all, while the other overload takes the value to set the property to. The latter is not const, and in many cases both will return the (pre-modification) value.

Iterators are an interesting intersection. Most iterators return references to objects in their containers. But the Input/OutputIterator distinction makes it possible for input iterators to generate values that aren't part of some container. Their operator* could return a value rather than a reference to an object.

Similarly, output iterators often have their operator* return a proxy-object which behaves like a reference. This proxy uses the assignment operator to set the value into the output stream, without having to return an actual value of that type.

But in virtually all cases in the standard library, you have one function name with multiple overloads based on the const-ness of the source object.

The most prominent case of the standard breaking this rule is atomic::load/store, which are independently named functions. One could have made them the same function, but being able to visually distinguish atomic load operations from stores is pretty important, since they can adversely affect the functionality of your code.

That being said, C++ as a whole has no guidelines on this. The above is just how the standard library handles it in most cases. Other libraries will frequently use get/set. Some libraries will call out get but not setting functions.