#c #templates #language-lawyer #template-argument-deduction
#c #шаблоны #язык-юрист #шаблон-аргумент-вывод
Вопрос:
Рассмотрим следующий код:
template<typename>
struct S
{
operator S<intamp;>();
};
template<typename T>
void f(S<Tamp;>);
int main()
{
f(S<intamp;amp;>{}); // gcc ok
// clang error
}
gcc использует оператор преобразования для временного аргумента, возвращая S<intamp;>
который соответствует S<Tamp;>
, и принимает вызов.
clang не учитывает оператор преобразования, не может сопоставить Tamp;
с intamp;amp;
и отклоняет вызов.
Итак, что, по словам языка, должно произойти здесь?
Комментарии:
1. Я был сбит с толку, пожалуйста, не обращайте на это внимания. Вывод аргумента шаблона завершается неудачей, разрешение перегрузки завершается неудачей, и больше ничего не рассматривается, по крайней мере, я так думаю.
2. @PasserBy Да, вывод завершается неудачей, но только в одном случае, а не в другом. Я хочу знать, какой из них, если таковой имеется, правильный.
3. Под этим я подразумеваю, что gcc неверен.
4. @PasserBy Хорошо, спасибо. Если вы можете найти отчет об ошибке, это было бы здорово. Если вы знаете, почему gcc неверен, тогда ответ тоже был бы прекрасен.
5. Это может помочь. Я думаю, что clang прав в этом вопросе…
Ответ №1:
GCC здесь, безусловно, ошибочен: Tamp;
и Tamp;amp;
— это разные строки в [temp.deduct.type]/8 и, следовательно, несовместимы. Почему это происходит, неясно. Было бы разумнее ошибиться в другом направлении: если бы параметр был объявлен как S<Tamp;amp;>
, а аргумент имел тип S<intamp;>
, по крайней мере, было бы T
(т. е., intamp;
) такое, что (из-за свертывания ссылки) типы параметра и аргумента были одинаковыми. (Также было бы легко допустить ошибку, сказав, что была задействована универсальная ссылка.)