Я обнаружил несоответствие между G CC и clang (большой диапазон версий, протестированных на godbolt - у всех было одинаковое расхождение) с сопоставлением операторов преобразования. Теперь с использованием более короткого кода воспроизведения Барри - также доступен по адресу godbolt .
struct X {
template <typename T>
operator T const&() const;
};
int i = X();
Если operator T const&() const
должно совпадать при преобразовании в int
(кланг говорит, что да / G CC нужно operator T() const
чтобы избежать:
<source>:6:9: error: cannot convert 'X' to 'int' in initialization
6 | int i = X();
| ^~~
Соответствующая часть стандарта C ++ 17 - 15.3 Преобразования [class.conv] . В этом разделе 15.3.5 говорится ...
Функция разрешения перегрузки (16.3.3) выбирает наилучшую функцию преобразования для выполнения преобразования.
..., что почти важно. 16.3.3 - раздел для Лучшая жизнеспособная функция [over.match.best] , но обычно работает в комбинации 16.3.2 жизнеспособных функций [over.match.viable] . В стандарте не представляется явным, что 16,3 .2 применяется здесь, но при условии, что в 16.3.2.1:
из набора функций-кандидатов, сконструированных для данного контекста (16.3.1), выбирается набор жизнеспособных функций
Что поднимает вопрос о том, считает ли G CC operator const T&() const
кандидат, который не является жизнеспособным, или даже не кандидат. Однако требования к кандидату на действительность очень просты: правильное количество аргументов и "для каждого аргумента должна существовать неявная последовательность преобразования (16.3.3.1), которая преобразует этот аргумент в соответствующий параметр ... «, что, очевидно, здесь верно, поэтому я считаю, что G CC не должен рассматривать operator const T&() const
кандидата, что приводит нас к 16.3.1 функциям-кандидатам и спискам аргументов [over.match.funcs] и, в частности, 16.3.1 / 7:
В каждом случае, когда кандидат является шаблоном функции, кандидаты-специализации шаблона функции генерируются с использованием вывода аргумента шаблона (17.8.3, 17.8.2) , Затем эти кандидаты обрабатываются как функции-кандидаты обычным способом.
Учитывая, что template <typename T> void f(const T&);
можно вызывать с типом аргумента int
, я думаю, G CC должен был рассмотреть Оператор преобразования является действительным кандидатом, как и Clang.
Я был бы признателен за подтверждение / мысли, хотя. Если люди согласны, я сообщу об ошибке против G CC.