Making an unknown friend
template<typename T>
class List
{
protected:
class a {
int x;
int y;
private:
friend class b; // <------------ Why this is not an error?
};
template <typename U > class b { //If that is not a error this should be an error
int z;
U y;
};
public:
List() {
a* ptr = (a *)new unsigned char[sizeof(a)];
}
};
int main() {
List<int> mylist;
}
Please go through this link, I have my questions as comments in the code. I am trying to make another class a friend of my class. But that class is not know at the time of making friend. What is the C++ rule that allows for it. Later I am defining that class in such a way that, it is incompatible with the friend declaration. Why is that not throwing an error. Thanks
//Run this- it now will compile for you
Yes your code is invalid! This is an interesting show of how templates can change meaning of code in subtle ways. The following code is valid:
Standard says at 7.3.1.2/3
When is it a "first declared class"? It says that too there
The lookup for "class b" is delegated from 7.1.5.3/2 to 3.4.4 which in turn delegates to unqualified name lookup at 3.4/7. All the question now is whether the template-name "b" is visible in the friend declaration class a. If it isn't, the name is not found and the friend declaration will refer to a new declared class at global scope. 3.3.6/1 about the scope of it says
Ignoring a few pedantic points that would make this wording not apply to here (which were a defect but are fixed in the C++0x version of that paragraph which also makes this easier to read), this list does not include the friend declaration as an area where that template name is visible.
However, the friend was declared in a member class of a class template. When the member class is instantiated different lookup applies - the lookup for friend names declared in a class template! The Standard says
So the following code is invalid:
When that causes
List<int>::a
to be implicitly instantiated, the namea
is looked up at "// POI" as if there would have been an explicit specialization declared. In that case, the templateList::b
has already been declared, and this lookup will hit it and emit an error because it's a template and not a non-template class.The code is ill-formed and Comeau rejects it giving the following error
I think this is a bug in g++. Intel C++ rejects it too. You can fix the code by defining class
B
aboveA
.