Here is something I observed across various compilers. It seems there are compiler bugs.
template <int I>
struct X
{ };
int main(void)
{
X<(16 > 1)> a; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
X<(int(16) > 1)> b; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
X<(16 >> 1)> c; // Works on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
X<(int(16) >> 1)> d; // Fails on vc9, works on g++ 4.1.2, works on Comeau 4.3.10.1
X<16 > 1> e; // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
X<int(16) > 1> f; // Fails on vc9, fails on g++ 4.1.2, fails on Comeau 4.3.10.1
X<16 >> 1> g; // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
X<int(16) >> 1> h; // Fails on vc9, works on g++ 4.1.2, fails on Comeau 4.3.10.1
}
Why is that inconsistency? What is allowed/disallowed by the standard? Such behavior is also responsible for syntax error while using BOOST_AUTO on vc9. It appears to me that Comeau is doing the right job by rejecting all the expressions without parenthesis.
The rules are as follows for C++03:
After name lookup (3.4) finds that a name is a template-name, if this name is followed by a
<
, the<
is always taken as the beginning of a template-argument-list and never as a name followed by the less-than operator. When parsing a template-id, the first non-nested>
[foot-note: A>
that encloses the type-id of adynamic_cast
,static_cast
,reinterpret_cast
orconst_cast
, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description. ] is taken as the end of the template-argument-list rather than a greater-than operator.
So the result is:
X<(16 > 1)> a; // works
X<(int(16) > 1)> b; // works
X<(16 >> 1)> c; // works
X<(int(16) >> 1)> d; // works
X<16 > 1> e; // fails
X<int(16) > 1> f; // fails
X<16 >> 1> g; // works (">>" is not a ">" token)
X<int(16) >> 1> h; // works (">>" is not a ">" token).
However, in C++0x the following are the rules
After name lookup (3.4) finds that a name is a template-name, or that an operator-function-id refers to a set of overloaded functions any member of which is a function template, if this is followed by a
<
, the<
is always taken as the delimiter of a template-argument-list and never as the less-than operator. When parsing a template-argument-list, the first non-nested > [foot-note: A>
that encloses the type-id of adynamic_cast
,static_cast
,reinterpret_cast
orconst_cast
, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description.] is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested>>
is treated as two consecutive but distinct>
tokens, the first of which is taken as the end of the template-argument-list and completes the template-id.
Result will be
X<(16 > 1)> a; // works
X<(int(16) > 1)> b; // works
X<(16 >> 1)> c; // works
X<(int(16) >> 1)> d; // works
X<16 > 1> e; // fails
X<int(16) > 1> f; // fails
X<16 >> 1> g; // fails (">>" translated to "> >")
X<int(16) >> 1> h; // fails (">>" translated to "> >")
Be sure to disable C++0x mode in comeau when testing