Re: Template friendship to nested template class
Mycroft Holmes <psion.s5@gmail.com> wrote:
template <typename T>
class OUTER
{
int private_;
template <long A, long B>
struct INNER
{
int doIt(OUTER<T> x) {return x.private_; }
};
template <long A, long B>
friend struct INNER;
public:
int exec() { return INNER<3,4>().doIt(*this); }
};
int main()
{
OUTER<double> x;
return x.exec();
}
Both VC and gcc are happy with this code, but the intel compiler is
not, and in fact Comeau reports a detailed reason for the failure:
(btw, Comeau reports 3 errors, but only the first is meaningful; the
latest intel compiler v11 only reports the 2 irrelevant errors,
omitting the first...)
First, I'd like to point you to DR45:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
The resolution is that a nested class is a member of its enclosing
class, and has the same access as any other member. So the friend
declaration is not required.
While not officially part of the standard, I believe most modern
compilers incorporate DR45. In particular, Comeau compiles your example
with the friend declaration removed completely.
Second, your example as written appears to be invalid for reasons Victor
has pointed out: your friend declaration refers to ::INNER, not to
OUTER::INNER. However these forms don't compile either:
template <long A, long B>
friend struct OUTER::INNER;
template <long A, long B>
friend struct OUTER<T>::INNER;
I'm not sure why - it looks like these should work. Anyway, as a
workaround, this compiles (at least with Comeau, I didn't test with
others):
template <typename U>
template <long A, long B>
friend struct OUTER<U>::INNER;
This doesn't quite do the same thing - it grants a broader friendship
than originally intended - but may be good enough.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925