Следует ли рассматривать операторы преобразования для вывода аргумента шаблона функции?

#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; ) такое, что (из-за свертывания ссылки) типы параметра и аргумента были одинаковыми. (Также было бы легко допустить ошибку, сказав, что была задействована универсальная ссылка.)