0

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?

Sparkler
  • 2,581
  • 1
  • 22
  • 41
  • 1
    What about `std::cout << str_manip(str)`? Is that supposed to use the in-place of version of the copying version? – François Andrieux Nov 13 '18 at 19:08
  • 1
    Can I just say that having two functions with the same names where one of them modifies the input and the other doesn't... that's wildly dangerous. Someone is guaranteed to get it wrong and make a bug in the code. Please don't do that. – Mooing Duck Nov 13 '18 at 19:20

2 Answers2

1

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.

contrapants
  • 775
  • 4
  • 16
1

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) {...}
anatolyg
  • 26,506
  • 9
  • 60
  • 134