Search code examples
c++c++11template-specializationauto

Error using auto for return type of specialised template function


consider the following code snippet (simplified from a more complex code):

#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;
}

Live example

If I try to compile it (either with gcc or clang) it results in the following error:

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

and I have to either:

  • explicitly declare res as a A_int object
  • call the method print() using the template keyword (res.template print<5>();)

in order to make this code compile.

I'm not really good in interpreting the Standard language, but as far as I understood the template keyword in a function call is needed when invoking a template member function on an object which type explicitly depends on a template parameter (see for instance this question).

In this case, I didn't expect the keyword template to be needed since res should be an object of type A, which is not explicitly dependent on a template parameter (even if it's the result of a template function call).

Could someone help me understanding where I'm wrong, and when the template keyword is actually needed?

Thanks in advance, and apologise if this is a duplicate question, but I could not find anything specific for similar issues.


Solution

  • For all the compiler knows, somewhere in the program it has not yet seen there exists a specialization of foo for some T that returns something other than A. So it cannot assume res is always A. Therefore, the type of res does in fact depend on the template parameter T, and then res.print is a dependent name after all.

    template keyword is then required to let the compiler know that the angle bracket after print is to be parsed as an angle bracket that forms part of a template-id, and not as a less-than operator.