Я хотел бы иметь возможность сделать следующее:
std::cout << str_manip("string to manipulate");
так же как
std::string str;
str_manip(str);
std::cout << str;
Для этого у меня есть две функции
#include <string>
// copying
std::string str_manip(std::string str)
{
// manipulate str
return str;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
но они выдают следующую ошибку:
error: call of overloaded 'str_manip(std::__cxx11::string&)' is ambiguous
Как я могу преодолеть это?
Проблема с этим вызовом:
std::string str;
str_manip(str);
std::cout << str;
Компилятор не знает, какая версия str_manip
звонить.
Вы можете изменить свои функции так:
#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
}
Теперь компилятор знает, что неоднозначный вызов должен быть функцией, которая принимает неconst
параметр. Вы также можете быть уверены, что ваш звонок, который возвращает std::string
к <<
Оператор не изменяет вашу строку.
Это может быть не то, что вы ищете, а ваш код
std::cout << str_manip("string to manipulate");
параметр для str_manip
это не string
но const char*
(на самом деле массив, но конвертируемый в char
указатель). Вы можете перегрузить, основываясь на этом.
std::string str_manip(const char* s)
{
std::string str(s); // create str
// manipulate str
return str;
}
Однако давайте посмотрим на общую картину. Когда ты видишь str_manip
в вашем коде это означает «изменить строку» или «создать новую строку на основе заданной строки»? Хотите ли вы быть намеренно амбивалентным по отношению к реальному смыслу?
Считайте, что вы читаете свой код через 1 год в будущем. Что вы будете думать, когда увидите звонок str_manip
— это мутирует свой параметр? Зависит ли ответ на предыдущий вопрос от контекста?
Цель написания кода — прояснить его, особенно в многопарадигмальном языке, таком как C ++. Так что, на мой взгляд, просто не перегружайте то, о чем вы думаете. Вместо этого сделайте 2 разных имени, например
void frobnicate_str(std::string&) {...}
std::string get_frobnicated_str(std::string) {...}