A C ++的语法问题涉及非平凡的模板和友元声明
题
下面的代码应该是自解释。我有一个关于所使用的语法(这是必须使用的语法)两个问题。我会永远感激,如果你能为我提供这些提出问题的答案。
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);
}
我已经验证,确实这是唯一正确的语法(我会很高兴地发现我错了)。我的问题是关于多的语法背后的推理,作为问题的身体解释说。
感谢您的帮助。
解决方案
为什么不在语法...
为什么不能语法是...
你还指望我们说?谁决定这句法(主要是斯特劳斯本人,据我所知)认为他们的语法比你的好。
哪一个是更好或更容易记住我不知道 - 但我觉得他们比你赚更多的意义。你可以自由地不同意,当然。
修改 的确定,亚历山大很好地回答问题#2 。约1:
不同的是,A<S>
名的键入的,这是预期的功能参数,而A
本身是的模板的名称,从类型将被创建,这是有道理的,如果你想要一个交朋友的模板的,而不是一个类型:
template <typename S>
void f (const A<S> &s); // A<S> being the name of a type
template <typename S>
friend struct A; // A being the name of a template
您在friend
的可以的交好特定模板的实例的而不是整个模板,但该模板必须已经由编译器是已知的(即声明)声明:
template< typename T >
class foo;
class bar {
friend class foo<int>; // foo<int> being the name of a specific instance of foo
};
所以结交一个模板是为异常(“通常” friend
声明声明的函数或类)和确实需要的不同的语法。
其他提示
虽然我不能说的为什么的这个语法是choosen,我只能说,我会支持的语言设计者做出两项决定 - 他们道理给我。问题2,你不但有一个模板,你有两个嵌套模板水平。为什么要语法定义模板类隐藏这一事实的模板成员?通过这种方式,它只是一个现有的模板语法的重新组合,而你需要特别规则合并为嵌套模板的模板参数在一个template<>
。
假设你的嵌套模板声明只是稍微复杂一些:
template <typename T, int I>
struct A {
template <typename S, I>
void f (const A<S, I> &s);
template <typename S, int J>
friend struct A;
// Question 1: why isn't the syntax 'friend struct A<S, J>' ?
// The semantic would stay, since we would like A<S, J> (for ANY S, J combination) to be friend of every A<T, I>..
private:
void g () const {}
};
template <typename T, int I>
template <typename S> // Question 2: Why can't the syntax be 'template <typename T, int I, typename S>' ?
void A<T>::f (const A<S> &s) {
s.g();
}
int main () {
A<bool, 5> abool;
A<char, 7> achar;
abool.f(achar);
}
突然,你的建议似乎不那么合理的或明显了。这组参数先走?假设你使用的C ++ 0x,有一个变量参数列表?
至于朋友声明,通过使您提出的语法(friend struct <S, J>
),你突然让编译器必须推断S
和J
旨在为模板参数,不应该从一些随机范围抓起。假如有人介绍了在同一作用域级别S
类型struct A
?这S
将申报friend struct A<S,J>
指什么?编译器怎么知道?是否合理具有引入名称的外部范围从根本上改变在嵌套范围声明的含义是什么?
如果你的意思是,声明应该阅读,总数:template <typename S, int J> friend struct A<S, J>
,那么为什么要朋友正向模板声明一下,从一个标准的模板声明有什么不同?它是多余的,包括模板变量名的模板的名称后,当你已经在template <typename S, int J>
部分提到这些。
我也觉得你的建议的语法会使搞清楚什么模板专业化做了很多的困难,因为你不得不看代码和关联事物的多个部分。
作为一个例子,我的版本A
的模板特是这样的:
template <typename T>
struct A<T, 5> {
};
和,你可以看到,这是奇怪的接近你的建议朋友向前声明的语法,这可能是很难说是否你打算指定一个专门的版本,或者没有。这将需要匹配了模板参数模板参数,而在途中它目前做,如果你没有,你是不是在谈论一个专业化模板参数。