【发布时间】:2013-10-27 20:45:51
【问题描述】:
C++03和C++11在[temp.friend]第一段中有:
[编辑引用。第一次尝试错过了措辞的第二个差异。]
对于不是模板声明的友元函数声明:
如果朋友的名字是合格的或不合格的template-id,朋友声明是指一个函数模板的特化,否则
如果朋友的名字是 qualified-id 并且在指定的类或命名空间中找到匹配的非模板函数,则朋友声明引用该函数,否则,
[C++03:] 如果朋友的名字是一个 qualified-id 并且在指定的类或命名空间中找到了一个函数模板的匹配特化,朋友声明是指该函数模板特化,否则,
[C++11:] 如果朋友的名字是一个 qualified-id 并且在指定的类或命名空间中找到匹配的函数模板,朋友声明引用推导的该函数模板的特化,否则,
名称应为声明(或重新声明)普通(非模板)函数的 unqualified-id。
[措辞的变化对我来说似乎是澄清。虽然我猜可能有不同的方式来解释 C++03 关于“在类或命名空间中寻找专业化”的措辞。]
我对第三颗子弹很好奇。我编写此代码以尝试满足其要求,但 g++ 4.8.1 和 clang++ 3.4 都拒绝该代码,无论是使用 -std=c++03 还是 -std=c++11:
template <class T> class R;
namespace N {
template <class T> void test(const R<T>&);
}
template <class T>
class R {
friend void N::test(const R<T>&); // 8
int m;
};
template <class T>
void N::test(const R<T>& rec) { rec.m; }
int main() {
R<int> r;
N::test(r);
}
当然,如果我将第 8 行更改为
friend void N::test<>(const R<T>&);
第一个项目符号适用并且程序被接受。 g++ 会打印一个有用的警告,说朋友“声明了一个非模板函数”,并建议我可能想要这样做。为了清晰和安全,代码可能也会获得更多样式点。
但是上面的代码不应该被第三个项目符号覆盖并且有效吗?朋友声明不是模板声明,它使用不是 template-id 的 qualified-id 作为名称。并且没有与第二个项目符号匹配的非模板函数声明。
这只是两者共同的编译器错误吗?还是我误解了什么?如果有,有没有演示第三个项目符号的程序示例?
【问题讨论】:
-
+1 有趣。我怀疑
<>是“朋友的名字”的一部分。 -
@JohnDibling: qualified-id 包括 template-id,所以是的,
f<>是 qualified-id 一共。 -
@JohnDibling 是的,标记
<和>是 template-id 的一部分。 name 可以是 identifier、operator-function-id、literal-operator-id、转换函数 ID 或 模板 ID [basic/4]。 -
@aschepler:那这就是你的答案?
-
Related: Issue 674,这似乎暗示这个例子是良构的。
标签: c++ templates language-lawyer