In C++, the symbols '<' and '>' are used for comparisons as well as for signifying a template argument. Thus, the code snippet
[...] Foo < Bar > [...]
might be interpreted as any of the following two ways:
How does the parser for a C++ compiler efficiently decide between those two possibilities?
Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. Generic Programming is an approach to programming where generic types are used as parameters in algorithms to work for a variety of data types.In C++, a template is a straightforward yet effective tool.
Defining a Function Template A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.
"A function template is a template that is used to generate functions. A template function is a function that is produced by a template. For example, swap(T&, T&) is a function tem-plate, but the call swap(m, n) generates the actual template function that is invoked by the call."
If Foo
is known to be a template name (e.g. a template <...> Foo ...
declaration is in scope, or the compiler sees a template Foo
sequence), then Foo < Bar
cannot be a comparison. It must be a beginning of a template instantiation (or whatever Foo < Bar >
is called this week).
If Foo
is not a template name, then Foo < Bar
is a comparison.
In most cases it is known what Foo
is, because identifiers generally have to be declared before use, so there's no problem to decide one way or the other. There's one exception though: parsing template code. If Foo<Bar>
is inside a template, and the meaning of Foo
depends on a template parameter, then it is not known whether Foo
is a template or not. The language standard directs to treat it as a non-template unless preceded by the keyword template
.
The parser might implement this by feeding context back to the lexer. The lexer recognizes Foo
as different types of tokens, depending on the context provided by the parser.
The important point to remember is that C++ grammar is not context-free. I.e., when the parser sees Foo < Bar
(in most cases) knows that Foo
refers to a template definition (by looking it up in the symbol table), and thus <
cannot be a comparison.
There are difficult cases, when you literally have to guide the parser. For example, suppose that are writing a class template with a template member function, which you want to specialize explicitly. You might have to use syntax like:
a->template foo<int>();
(in some cases; see Calling template function within template class for details)
Also, comparisons inside non-type template arguments must be surrounded by parentheses, i.e.:
foo<(A > B)>
not
foo<A > B>
Non-static data member initializers bring more fun: http://open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#325
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With