I've followed your suggestion and it appears that it works. I thought that the declaration of a
template friend function would be something like:
<code>
template<class T> class foo {
public:
foo(T t): t(t) {}
protected:
T t;
template<class T> friend void inspect_foo(foo<T> f);
};
template<class T> void inspect_foo(foo<T> f) {
cout<< f.t<< endl;
}
</code>
Is there a reason for that not to work?
The above is reported as "shadowing" by my compiler, and, at the same
time, it tells that it happens to be an error.
I don't really know the rationale behind making such "shadowing" an
error instead of (just) a warning.
By the way, just for fiddling, I've made this test which sort of take
advantage of NOT shadowing T (well, OK, I am not allowed to shadow it in
any case, so no big "taking"):
//-------
#include <iostream>
using namespace std;
template<class T> class foo {
public:
foo(T t): t(t) {}
T get_t() {
return t;
}
private:
T t;
template<class U> friend void inspect(foo<U> f, T t);
};
template<class W> void inspect(foo<W> f, int i) {
// accesses the private interface
cout << f.t << endl;
cout << i << endl;
}
template<class W> void inspect(foo<W> f, double d) {
// accesses the private interface
cout << f.t << endl;
cout << d << endl;
}
template<class W> void inspect(foo<W> f, const char* cstr) {
// accesses only the public interface
cout << f.get_t() << endl;
cout << cstr << endl;
}
int main() {
foo<int> i(42);
foo<double> d(4.2);
// (int, int) compiles as a friend
inspect(i, 78);
// (double, double) compiles as a friend
inspect(d, 7.8);
// (not an int, int) error: not a friend!
//inspect(d, 78);
// (not a double, double) error: not a friend!
//inspect(i, 7.8);
// (whatever, const char*) compiles - not a friend, no need to
inspect(i, "int");
inspect(d, "double");
return 0;
}
//-------
In the above code only the "inspect" instantiations whose second
parameter's type matches the (inspect's) template type are allowed to
access the "innards" of "foo" (whatever its type), all the others can
only access its public interface.
I'm not able to see any immediate use of this - although I think someone
must have used something like this, somewhere.
The point could be: to do the above I've "had" to use the name "T" in
the declaration of "inspect", within of "foo".
Had I used "T" as "inspect" template parameter (shadowing "foo"'s
template parameter) that trick would have been impossible.
And with "trick" I mean "declaring, with a single line, a friend
function that is a /true friend/ only when its parameters equate each other"
Still, that's not enough of a reason to forbid shadowing.
I'm not so sure I could be able to understand all that I wrote here above.
That could be my English' fault. That could be the late hour's fault.
That could well be the templates' fault - or my understanding of them,
more likely ;-)
Templates: lovely, tricky bastards. Good night.