у меня есть шаблон функции (C ++)
template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
и перегруженная функция
template<typename T>
void print_to_default_file(T &obj, std::string objS) // or char* objS
Класс ADDON
имеет перегрузку оператора следующей подписи
void operator=(const std::string)
Проблема в том, что когда я делаю
print_to_default_file («тест», «куда я пойду»)
Звонит первый, но я хочу позвонить второй. Я устал от char * вместо std :: string, но результат тот же.
Может ли кто-нибудь, пожалуйста, указать, что не так
ADDON упрощенная версия
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
ADDON(std::string in) {
s = in;
}
ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
Код, который вы нам показали
#include <iostream>
#include <string>
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
ADDON(std::string in) {
s = in;
}
ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
template<typename T>
void print_to_default_file(T &obj, ADDON addon = "")
{ std::cout << "first overload\n"; }
template<typename T>
void print_to_default_file(T &obj, std::string objS)
{ std::cout << "second overload\n"; }
int main()
{
print_to_default_file("test","where will I go");
}
не компилируется (онлайн выход) со следующей ошибкой
prog.cpp: в функции int main (): prog.cpp: 39: 52: ошибка: вызов
перегружен файл «print_to_default_file (const char [5], const char [16])»
неоднозначный prog.cpp: 39: 52: примечание: кандидаты: prog.cpp: 30: 6: примечание:
void print_to_default_file (T&, ADDON) [с T = const char [5]] prog.cpp: 34: 6: примечание: void print_to_default_file (T&, std :: string) [с
T = const char [5]; std :: string = std :: basic_string]
Причина в том, что поиск имени и вывод аргумента находят 2 кандидата: первая перегрузка требует const char*
в ADDON
преобразование, а вторая перегрузка const char*
в std::string
преобразование. Обе последовательности преобразования одинаково хорошо соответствуют друг другу, а восстановление при перегрузке неоднозначно, а ваша программа некорректна.
Просто измените вторую перегрузку, чтобы принять const char*
как параметр (а не как char*
, который не может связываться со строковыми литералами), и это будет лучшим совпадением для необработанных строковых литералов в качестве аргумента
template<typename T>
void print_to_default_file(T &obj, const char* objS) // but NOT char* objS
{ std::cout << "second overload\n"; }
Теперь вы получите вторую перегрузку (онлайн выход). Чтобы выбрать первую перегрузку, просто вызовите ADDON
конструктор в списке параметров
int main()
{
print_to_default_file("test", ADDON("where will I go"));
}
Обратите внимание, что это вызовет ADDON(const char[])
конструктор, а не ADDON(std::string)
один, так как последний потребует пользовательского преобразования (онлайн выход).
Крайне опасно иметь неявные конструкторы с одним аргументом. Всегда используйте explicit
Ключевое слово вокруг таких функций.
class ADDON {
std::string s;
public:
ADDON() {
s = "";
}
explicit ADDON(std::string in) {
s = in;
}
explicit ADDON(const char in[]) {
s = in;
}
void operator=(const std::string in) {
s = in;
}
std::string getString() {
return s;
}
};
Это также вызовет вторую перегрузку (онлайн выход), поскольку ADDON
Перегрузка не вызывает явно конструктор. Чтобы выбрать первую перегрузку, снова вызовите ADDON
конструктор в списке параметров.
Других решений пока нет …