代码
template <typename T>
void foo(const T& t)
{}
template <typename T>
class A
{
template <>
friend void foo<T>(const T& t)
{}
};
给出编译错误
"defining explicit specialization ‘foo<T>’ in friend declaration friend void foo<T>(const T& t)"
使用 GCC 编译时和
"error C3637: 'A<int>::foo' : a friend function definition cannot be a specialization of a unction template"
在VS2013中编译时
我知道这个标准是这么说的,但为什么呢?我想了解原因(在引擎盖下)有很多文章写着"明确的专业化不能成为朋友宣言",但我不明白为什么。有什么想法吗?
第一次(也可能是唯一一次)在类模板内声明显式专用化意味着显式专用化仅在模板实例化后"存在",无论声明是否依赖于模板参数。这会产生许多问题,并会导致在各种情况下违反 ODR,其中许多可能是格式不正确的 NDR;主要是因为@dyp在评论中提到的段落,[temp.expl.spec]/6
此外,类内部没有外部声明的友元函数定义使得此函数只能通过 ADL 调用。显然,如果显式专用化仅在调用具有关联参数类型时才适用,那绝对是荒谬的 - 同样,更不用说违反 ODR 了。
这些和其他原因使得这种结构过于复杂,但又不是很有益:您可以简单地将专用化添加为friend
,而不是以任何方式指示此专用化是实例化还是显式专用化。
friend void foo<T>(const T&);
然后,可以在命名空间范围中添加任何显式专用化。