Ошибка использования auto для типа возврата специализированной функции шаблона - PullRequest
0 голосов
/ 12 июля 2020

рассмотрите следующий фрагмент кода (упрощенный из более сложного кода):

#include <typeinfo>
#include <iostream>

struct A{
    template<int S>
    void print(){ std::cout << S << std::endl; }
};

struct B{};

template <class T>
A foo(int);

template<>
A foo<B>(int){ return A{}; }

template<class T>
int bar(int){
  auto res = foo<T>(0);
  std::cout << typeid(res).name() << std::endl;
  res.print<5>();       // This line gives an error
  return 0;
}

int main() {
  bar<B>(0);
  return 0;
}

Живой пример

Если я попытаюсь скомпилировать его (либо с помощью g cc или clang) это приводит к следующей ошибке:

main.cpp:21:16: error: expected primary-expression before ')' token
   21 |   res.print<5>();

, и я должен либо:

  • явно объявить res как A_int объект
  • вызов метода print() с использованием ключевого слова template (res.template print<5>();)

, чтобы этот код скомпилировался.

Я не очень хорош при интерпретации стандартного языка, но, насколько я понял, ключевое слово template в вызове функции необходимо при вызове функции-члена шаблона для объекта, тип которого явно зависит от параметра шаблона (см., Например, этот вопрос ).

В этом случае я не ожидал, что ключевое слово template понадобится, поскольку res должен быть объектом типа A, который явно не зависит от параметра шаблона (даже если это результат шаблона f unction call).

Может ли кто-нибудь помочь мне понять, где я ошибаюсь и когда действительно необходимо ключевое слово template?

Заранее спасибо и извиняюсь, если это повторяющийся вопрос , но я не смог найти ничего конкретного c для аналогичных проблем.

1 Ответ

0 голосов
/ 12 июля 2020

Насколько известно компилятору, где-то в программе, которую он еще не видел, существует специализация foo для некоторого T, которая возвращает что-то иное, чем A. Поэтому он не может предполагать, что res всегда равно A. Следовательно, тип res на самом деле зависит от параметра шаблона T, и тогда res.print в конце концов является зависимым именем. Тогда требуется ключевое слово

template, чтобы сообщить компилятору что угловая скобка после print должна анализироваться как угловая скобка, которая является частью template-id , а не как оператор «меньше».

...