Reputation: 73
For some reasons, I'd like to write code like this:
template<class T>
class C : public T
{
friend class T;
};
I think the code is clear. I want to have a class template which defines a class derived from the class passed to it as the template parameter, and to make things a little more complex, I'd like to define the base class as friend of the derived one. The code seems to be OK with MSVC compiler, but GNU C++ compiler complains a lot. What should I do to have the desired functionality?
Upvotes: 4
Views: 1057
Reputation: 56430
It is ill-formed, and is not valid C++ although it works in MSVC. The C++03 standard says this (7.1.5.3 §2):
3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the decla- ration the same way a simple-type-specifier introduces its type-name. If the identifier resolves to a typedef- name or a template type-parameter, the elaborated-type-specifier is ill-formed. [Note: this implies that, within a class template with a template type-parameter T, the declaration
friend class T;
is ill-formed. ] If name lookup does not find a declaration for the name, the elaborated-type-specifier is ill-formed unless it is of the simple form class-key identifier in which case the identifier is declared as described in 3.3.1.
For this same reason you can't do things like friend class std::string;
either, but you must befriend the std::basic_string
with the template parameters.
However the new C++11 spec allows a new syntax for declaring friends, which simply is (11.3 §3 of N3242):
friend <typename-specifier>;
This new syntax allows you to do what you want (I don't know if MSVC yet supports this though):
template<typename T>
class C : public T
{
friend T;
};
Upvotes: 6