The following code should be self explanatory. I have two questions regarding the used syntax (which is the syntax that must be used). I’ll be forever grateful if you could provide me with answers for these presented questions.
template <typename T>
struct A {
template <typename S>
void f (const A<S> &s);
template <typename S>
friend struct A;
// Question 1: why isn't the syntax 'friend struct A<S>' ?
// The semantic would stay, since we would like A<S> (for ANY S) to be friend of every A<T>..
private:
void g () const {}
};
template <typename T>
template <typename S> // Question 2: Why can't the syntax be 'template <typename T, typename S>' ?
void A<T>::f (const A<S> &s) {
s.g();
}
int main () {
A<bool> abool;
A<char> achar;
abool.f(achar);
}
I have verified that indeed this is the only correct syntax (I’ll be happy to find out I’m mistaken). My questions are more regarding the reasoning behind the syntax, as explained in the questions’ body.
Thanks for any help.
What do you expect us to say? Whoever decided this syntax (mostly Stroustrup himself, AFAIK) thought their syntax better than yours.
Which one is nicer or easier to remember I wouldn’t know – but I do find theirs making more sense than yours. You’re free to disagree, of course.
Edit: OK, Alexander has nicely answered question #2. About #1:
The difference is that
A<S>names a type, which is what is expected for a function argument, whileAby itself is the name of a template, from which types are to be created, which makes sense if you want to befriend a template instead of a type:You can befriend a specific template instance instead of the whole template, but for that the template must already be known by the compiler (i.e., declared) at the
frienddeclaration:So befriending a template is an exception (the "usual"
frienddeclarations declares a function or class) and does need the differing syntax.