Неоднозначность не подобрана компилятором

Мне пришлось потратить некоторое время на поиск и исправление ошибки, которую мне удалось выделить в следующем коде:

#include <iostream>

struct A
{
std::string S;
A(const std::string s) { S = s; }
};

void f1(A a) { std::cout << "f1:a.S = " << a.S << "\n"; }
void f1(const std::string s) { std::cout << "f1:s = " << s << "\n"; }

void f2(A a) { std::cout << "f2:a.S = " << a.S << "\n"; }

int main()
{
f1(A("test"));
f1(std::string("test"));

f2(A("test"));
f2(std::string("test"));

return 0;
}

Ошибка была вызвана пропущенной (мной и компилятором (?)) Неоднозначностью, созданной f1-функции: f2 ясно показывает, что оба f1(A) а также f1(std::string) применить к A, но при компиляции неоднозначность не улавливается компилятором, а при выполнении получается:

f1:a.S = test
f1:s = test
f2:a.S = test
f2:a.S = test

Это поведение правильно? Проблема с компилятором? Или просто старый ПИБКАК?

3

Решение

Ожидаемое вами поведение ожидается: двусмысленности нет. Неоднозначность разрешения перегрузки возникает, когда две перегрузки совпадают одинаково хорошо и обе являются «наилучшей перегрузкой».

Когда вы звоните f1 с аргументом типа A, первый f1 точное совпадение; второй f1 не совпадает вообще. Таким образом, f1 очевидно выигрывает при разрешении перегрузки.

Когда вы звоните f1 с аргументом типа std::string, первый f1 совпадения через конвертирующий конструктор A; второй f1 это точное совпадение. Второй f1 это лучшее совпадение: это точное совпадение, и никакого преобразования не требуется. Две перегрузки не совпадают одинаково хорошо, поэтому нет никакой двусмысленности. Второй f1 выигрывает при разрешении перегрузки.

8

Другие решения

Других решений пока нет …