In my current code, I want to have two functions with the same purpose, but different usages. (both functions I have in a "String::" namespace)
std::string ReplaceAll(const std::string &str, ....);
I also have:
void ReplaceAll(std::string &str, ...);
They do the exact same thing (takes a string to operate on, a string to find, and a string to replace it with), but I use them in different ways.
I have more than just 'ReplaceAll()', I want multiple versions of several different functions. (Since I can always implement one function by calling the other, it doesn't introduce code bloat, and bug-fixes or optimizations to one automatically effect the other).
The first is useful for passing as parameters, such as this type of situation: (Supposing ToLower() is the function we are talking about)
map[ String::ToLower(key) ] = value;
It works well. If it didn't return a value, I'd have to do this:
std::string lowercaseKey = key; String::ToLower(lowercaseKey); map[ lowercaseKey ] = value;
That makes code less clear when doing a series of operations, because you have boilerplate lines for every operation of the function, instead of just having each operation be self-explanatory.
However, when I'm operating on a single value, or a series of values, I don't want to go like this:
str = Operation(str); str = SecondOperation(str); str = OtherOperation(str); str = NextOperation(str);
I would much rather do the following, for code readability:
Operation(str); SecondOperation(str); OtherOperation(str); NextOperation(str);
But I can't have two different versions of the same function named the same thing, for two reasons:
1) It'd be confusing to read. Which version am I calling here, version A, or version B?
2) C++ wouldn't allow it, even if I wanted it - the function parameters are too identical so the function names would collide.
So what would you call the two functions to distinguish them?
I was thinking something like,
ReplaceAllOn(str, ...) //Operates 'on' str, and returns void. ReplaceAllFrom(str, ...) //Operates on a copy of str, and returns the copy.
Another possibility is using pointers for the 'operate on' version of functions, letting the & symbol indicate what's going on.
ReplaceAll(&str, ...) str = ReplaceAll(str, ...)
However, I prefer using references when I know the variable address won't change during the function, and there's still the possibility of accidentally going:
ReplaceAll(str, ...) //Returning a copy, and having no effect, because you forgot the '&' so it called the wrong function. Hard to spot mistake when scanning code visually.
What I'd really love is a compiler error if I'm using the wrong function, but I can't think of a way to make that happen.
Blah = OperateOn(blah); //Compiler error: Blah = void is invalid. (This error already works) OperateOnCopyOf(blah); //Compiler error: You're not assigning the return value to anything, you moron! (Sadly, this error my compiler doesn't inform me of)