Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when calling an Integral template member function with g++ and clang++ [duplicate]

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.

like image 740
Tachikoma Avatar asked Aug 30 '15 19:08

Tachikoma


1 Answers

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.

like image 87
Alan Stokes Avatar answered Oct 15 '22 07:10

Alan Stokes