Templates as friends of C++ classes
Every programmer knows that class can be declared as friend of another class. This notation is very familiar. It is less known is that adding a friend specification creates a forward declaration for the friend class on the namespace level if this class is not defined yet. Look at the example:
Here you see that parser issued a syntax error at the line 2 because the class C1 is not yet defined. On the contrary, the function prototype on the line 9 compiles fine because friend specification on the line 6 generated forward declaration for C1.
In some cases it is necessary to have access from the code of template to the data fields and methods of a class. The syntax for this is the following:
Specification on the line 6 tells that all instantiations of template T1 will be friends of the current class. Line 2 contains forward declaration of the class template. If this line would be missing, this will not change anything. Friend specification will create forward declaration for this class template exactly in the same way as it was done for simple class in the previous example.
This notation may sound a bit strange and not really logical. Somebody might prefer to write it like this:
friend template <class p1> class T1;
But this will be against the C++ grammar. Compiler will issue a syntax error. For example Microsoft's C++ compiler issues a pair of unclear messages that do not give any clue on what is going on and what might be wrong. Here are pieces of the C++ grammar that are related to declaring class template as friend:
As you can see the possible forms of the friend specification are deeply dug in the grammar. Besides the formal rules, C++ standard tells in human language that friend prefix can be used only with elaborated type specifiers and not with other possible forms of declaration. Functions and function templates can also be friends.
When a friend specification is processed according to the grammar, the DeclTypeSpecifier is assembled first and it already contains the friend specifier inside. Only later on when the DeclTypeSpecifier is promoted into Declaration the TemplateDeclarationHeader is taken into account. This is how the C++ grammar is defined in the standard. Compilers only follow this grammar.
If you find this article useful or if you want to propose topic for a similar article, send us a note using the contacts page.