tags:

views:

134

answers:

2

I'm having some trouble getting this code to compile on Linux but it works perfectly in Windows.

Windows compiler: Visual Studio 2005

Linux compiler: gcc version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)

class DoSomething
{
  public:
    template <class DataType>
    bool Execute()
    {
       //do something here
    }
};


template <class Operator>
TypeSwitch(int DataTypeCode, Operator& Op)
{
   switch (DataTypeCode)
   {
     case 1: return Op.Execute<char>();
     case 2: return Op.Execute<int>();
     //snip;
   }
}  

//To call the operator
TypeSwitch(Code,DoSomething);

In Windows this code works perfectly and does exactly what I want it to. In Linux, I get the errors:

error: expected primary-expression before '>' token

error: expected primary-expression before ')' token

for each of the lines with the case statement.

Any ideas?

Thanks, Mike

+13  A: 

The problem is that when the compiler encounters Op.Execute<char>(); and tries to parse it, it gets confused.

Op is a dependant name, so the compiler doesn't know much about its members. So it doesn't know that Execute is a template function. Instead, it assumes that the < means less than. That you're trying to compare some unknown Execute member to something else.

So instead, the line should look like this:

case 1: return Op.template Execute<char>();

Now the compiler knows that Execute is a template, so when it encounters < it is not "less than", but the beginning of the template parameters.

The problem is similar to how you need typename when specifying types belonging to a dependent name. When you're referring to a template member function, and the template arguments are given explicitly, you need the template keyword.

GCC's behavior is correct, and MSVC is too lenient. If you add the template keyword, your code will work in both compilers (and be correct according to the standard)

jalf
Welcome to the wonderful, magical world of C++ template parsing rules!
Tyler McHenry
Ah, thanks! I'll give this a try when I get back to work Monday morning, but your description sounds just right. Just love the subtleties with templates!
miked
Just a follow up for anyone else who needs this: I just tried this an found that there's a known bug in MSVC that the above fix doesn't work. So in Windows you need Op.Execute<char>() and in not-windows you need Op.template Execute<char>().
miked
It's always worked for me in VS2008. Don't know if it was a problem in 2005. Got a link to that bug report?
jalf
On reading the bug report more carefully, I don't think it's the same issue: http://support.microsoft.com/kb/241949However, I cannot get Op.template Execute<char>() to compile on windows (and solaris), but it works perfectly in Linux and Mac (both GCC). For now I've just #ifdefed it and will worry about it later if I have to.
miked
Yeah, it's a different issue. Not sure why it doesn't work for you on Windows and Soliaris. If you add the code to the question, I'll take a look
jalf
+1  A: 
 case 1: return Op.template Execute<char>();
 case 2: return Op.template Execute<int>();

See: template as qualifier

Also, TypeSwitch() returns a bool

moonshadow