我想做一个单一的专业化的朋友,如下图所示。我尝试了以下与C++20,但程序得到 * 拒绝的clang和被接受的GCC和MSVC *。
template <class T>
struct Ext {
struct Inner
{
int m{};
};
/*Is there a way to make this specialization work with all the compilers?
Note that I know that I can write template<typename S> friend void fun2(Ext<T>::Inner&)
but I only want to make this specialization a friend
*/
friend void fun2<T>(typename Ext<T>::Inner&); //C++20: works in gcc and msvc but rejected by clang
};
template <class T>
void fun2(typename Ext<T>::Inner &p)
{
p.m = 10;
}
int main()
{
Ext<int>::Inner x;
fun2<int>(x);
}
字符串
Demo
我有两个问题:
1.有没有一种方法可以使这个特殊化void fun2<T>(typename Ext<T>::Inner&);
成为友元,这样程序就可以被所有的编译器接受?也就是说,我想要一个变通方法,使这个特殊化成为友元,而不是所有的Ext
。
1.上面的程序(在我的帖子中)在C++20中是格式良好的吗?
Clang说:
<source>:13:16: error: no candidate function template was found for dependent friend function template specialization
13 | friend void fun2<T>(typename Ext<T>::Inner&); //C++20: works in gcc and msvc but rejected by clang
| ^
<source>:24:15: error: use of undeclared identifier 'x'
24 | fun2<int>(x);
型
1条答案
按热度按时间ny6fqffe1#
看起来这个程序是格式错误,gcc和msvc在接受这个程序时是错误的。
首先注意
fun2<T>
指的是一个函数模板的特殊化。从temp.friend:1.类或类模板的友元可以是函数模板或类模板,**函数模板或类模板的特化,也可以是非模板函数或类。对于非模板声明的友元函数声明:
1.1)如果友元的名称是限定或非限定的template-id,则友元声明引用函数模板的特殊化,否则,
1.2)
第1.3节)
第1.4节)
从temp.deduct.decl开始:
1.**如果声明的declarator-id引用了函数模板的专门化,则会执行模板参数推导来标识声明所引用的专门化。具体来说,这是针对显式示例化,显式专门化,和某些友元声明。**这样做也是为了确定释放函数模板专门化是否匹配放置运算符new([basic.stc.dynamic.deallocation],[expr.new])。在所有这些情况下,P是被认为是潜在匹配的函数模板的类型,A是来自声明的函数类型,或者是与[expr. new]中描述的放置操作符new匹配的deallocation函数的类型。演绎过程如[temp. dice.type]中所述进行。
1.如果对于这样考虑的函数模板集,在考虑了偏序([temp.func.order])之后没有匹配或有多个匹配,则演绎失败,并且在声明的情况下,程序是病态的。
(强调我的)
在我们的例子中,集合是空的,所以没有匹配,这意味着程序是病态的,就像上面引用的参考文献一样。