17

I get an error <: cannot begin a template argument list on g++ compiler. Code

template<typename T> class SomeClass;
class Class;

SomeClass<::Class>* cls;
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Pirate
  • 171
  • 1
  • 3
  • 1
    The new standrard (C++0x) addresses the issue of >> like in A>. Doesn't it address this issue as well? Incidentally, Micorosoft compilers don't give error on this (I know that they technically should, but it's good they don't) – Armen Tsirunyan Oct 17 '10 at 09:59
  • @ArmenTsirunyan yes, this was fixed in C++0x which became C++11 although the fix for `>>` was done in section `14.3` which is different than the fix for `<::` which is a modification of the maximal much rule. So both annoying but different core issues at work. I detail this in my answer. – Shafik Yaghmour Jul 27 '14 at 02:30

4 Answers4

35

According to the Maximal Munch tokenization principle a valid C++ token must collect/have as many consecutive characters as possible.

<: is a digraph (an alternative representation of symbol [).

                           Digraph  Equivalent
                              <:          [
                              :>          ]
                              <%          {
                              %>          }
                              %:          #

So SomeClass<::Class>* cls; is interpreted as SomeClass[:Class>* cls; which doesn't make any sense.

Solution: Add a whitespace between < and :

  SomeClass< ::Class>* cls;
            ^
            | 
           White Space
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
10

Try the following instead:

SomeClass< ::Class>* cls;

You can find more info in this question about digraphs. This question about trigraphs could be helpful also.

Community
  • 1
  • 1
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
7

With C++11 the answer to this question changes a bit.

Pre C++11

Previous to C++11 the maximal munch rule which is used in lexical analysis to avoid ambiguities and works by taking as many elements as it can to form a valid token caused this:

<::

to generate the following tokens as:

<: :

<: is a digraph which translates to [ and so you end up with:

SomeClass[:Class>* cls;

which is not valid code.

We can confirm that this is the case by going to the draft C++ standard section 2.4 Preprocessing tokens which says:

If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail.

and provides a couple of examples including the following classical maximal munch question:

[ Example: The program fragment x+++++y is parsed as x ++ ++ + y, which, if x and y are of built-in types, violates a constraint on increment operators, even though the parse x ++ + ++ y might yield a correct expression. β€”end example ]

C++11

In C++11 this changes, a rule was carved out for this case and the draft C++11 standard added the following:

Otherwise, if the next three characters are <:: and the subsequent character is neither : nor >, the < is treated as a preprocessor token by itself and not as the first character of the alternative token <:.

to section 2.5 Preprocessing tokens. So this code will no longer produce and error in C++11.

This change came from defect report: 1104

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
1

Put spaces around the < characters:

SomeClass < ::Class > * cls;

You only actually need to separate < and :, but I like symmetry.

JoshD
  • 12,490
  • 3
  • 42
  • 53