Question

A friend and I were discussing C++ templates. He asked me what this should do:

#include <iostream>

template <bool>
struct A {
    A(bool) { std::cout << "bool\n"; }
    A(void*) { std::cout << "void*\n"; }
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new A< b > (c) > (d);
}

The last line in main has two reasonable parses. Is 'b' the template argument or is b > (c) the template argument?

Although, it is trivial to compile this, and see what we get, we were wondering what resolves the ambiguity?

Was it helpful?

Solution

AFAIK it would be compiled as new A<b>(c) > d. This is the only reasonable way to parse it IMHO. If the parser can't assume under normal circumstances a > end a template argument, that would result it much more ambiguity. If you want it the other way, you should have written:

new A<(b > c)>(d);

OTHER TIPS

As stated by Leon & Lee, 14.2/3 (C++ '03) explicitly defines this behaviour.

C++ '0x adds to the fun with a similar rule applying to >>. The basic concept, is that when parsing a template-argument-list a non nested >> will be treated as two distinct > > tokens and not the right shift operator:

template <bool>
struct A {
  A(bool);
  A(void*);
};

template <typename T>
class C
{
public:
  C (int);
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new C <A< b  >>  (c) > (d); // #1
    new C <A< b > >  (c) > (d); // #2
}

'#1' and '#2' are equivalent in the above.

This of course fixes that annoyance with having to add spaces in nested specializations:

C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"

The C++ standard defines that if for a template name followed by a <, the < is always the beginning of the template argument list and the first non-nested > is taken as the end of the template argument list.

If you intended that the result of the > operator be the template argument, then you'd need to enclose the expression in parentheses. You don't need parentheses if the argument was part of a static_cast<> or another template expression.

The greediness of the lexer is probably the determining factor in the absence of parentheses to make it explicit. I'd guess that the lexer isn't greedy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top