5

I'm currently stuck on a compilation error, which I can't really identify...

Here's a minimal working example:

#include <iostream>

template <typename T, int R>
class a_type
{
public:
     template <int N>
     double segment()
      {
           return 42;
      }
};

template <int M>
double func()
{
     a_type<double, M> a;
     return a.segment<1>();
}

int main(int argc, char *argv[])
{
     std::cout << func<10>() << std::endl;
     return 0;
}

The error message from GCC reads:

g++ main.cpp -o main
main.cpp: In function 'double func()':
main.cpp:18:26: error: expected primary-expression before ')' token
      return a.segment<1>();
                          ^
main.cpp: In instantiation of 'double func() [with int M = 10]':
main.cpp:23:28:   required from here
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
      return a.segment<1>();
                  ^

Clang also says something similar:

clang++ main.cpp -o main
main.cpp:18:26: error: expected expression
     return a.segment<1>();
                         ^

So based on GCC's error message, 'a.segment' is a member function call missing the parentheses, which obviously gets rejected. But that does not make sense at all, since I don't see any reason for treating that expression as such. Moreover, if I change M to any integral number on line 17, like so:

#include <iostream>

template <typename T, int R>
class a_type
{
public:
     template <int N>
     double segment()
      {
           return 42;
      }
};

template <int M>
double func()
{
     a_type<double, 58> a;
     return a.segment<1>();
}

int main(int argc, char *argv[])
{
     std::cout << func<10>() << std::endl;
     return 0;
}

then the code compiles and produces the expected result.

I would be very happy if somebody could enlighten me and show me what I am missing here.

Tachikoma
  • 179
  • 2
  • 9

2 Answers2

4

The compiler doesn't know that a.segment is a template (it might depend on the value of M). So you have to tell it:

return a.template segment<1>();

In your second example it knows everything about the type of a, and so there is no problem.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • Many thanks for your answer! I had completely forgotten about that use of the template keyword. Guess my C++ was getting a little rusty ;-) – Tachikoma Aug 31 '15 at 06:24
1

The compiler tells you that it has problems with

 a_type<double, M> a;
 return a.segment<1>();

because it cannot tell what members a can have, as it is a template (that might be specialized for some values of M).

main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<' return a.segment<1>(); ^

If segment is a template, it would be treated as segment<1>. If segment is a member variable of a, it should be compiled as a.segment < 1. How is the compiler to know?

You can fix this by using

return a.template segment<1>();
Bo Persson
  • 90,663
  • 31
  • 146
  • 203