How to overload an in-place and a copying string manipulation functions?

43 views Asked by At

I would like to be able to do the following:

std::cout << str_manip("string to manipulate");

as well as

std::string str;
str_manip(str);
std::cout << str;

For this, I have two functions

#include <string>

// copying
std::string str_manip(std::string str)
{
        // manipulate str
        return str;
}

// in-place
void str_manip(std::string& str)
{
        // manipulate str
}

but they produce the following error:

error: call of overloaded 'str_manip(std::__cxx11::string&)' is ambiguous

How can I overcome this?

2

There are 2 answers

0
contrapants On BEST ANSWER

The problem is with this call:

std::string str;
str_manip(str);
std::cout << str;

The compiler doesn't know which version of str_manip to call.

You can change your functions to look like this:

#include <string>

// copying
std::string str_manip(const std::string& str)
{
        std::string dup = str;
        // manipulate dup
        return dup;
}

// in-place
void str_manip(std::string& str)
{
        // manipulate str
}

Now, the compiler knows that the ambiguous call has to be the function that takes the non-const parameter. You can also be sure that your call that returns a std::string to the << operator isn't modifying your string.

0
anatolyg On

This might be not the thing you are looking for, but for your code

std::cout << str_manip("string to manipulate");

the parameter to str_manip is not a string but const char* (actually an array, but convertible to a char pointer). You can overload based on that.

std::string str_manip(const char* s)
{
    std::string str(s); // create str
    // manipulate str
    return str;
}

However, let's look at the big picture. When you see str_manip in your code, does this mean "change the string" or "make a new string based on the given string"? Do you want to be intentionally ambivalent on the real meaning?

Consider yourself reading your code in 1 year in future. What will you think when you see a call to str_manip - does this mutate its parameter? Does the answer to the previous question depend on context?

The goal in writing code is to make it clear, especially in a multi-paradigm language like C++. So, in my opinion, just don't do overloading that you are thinking about. Instead, make 2 distinct names, like

void frobnicate_str(std::string&) {...}
std::string get_frobnicated_str(std::string) {...}