c++ 在gcc和msvc中可以使用特定的专门化,但在clang中不行

0ve6wy6x  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(97)

我想做一个单一的专业化的朋友,如下图所示。我尝试了以下与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);

ny6fqffe

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])之后没有匹配或有多个匹配,则演绎失败,并且在声明的情况下,程序是病态的。
(强调我的)
在我们的例子中,集合是空的,所以没有匹配,这意味着程序是病态的,就像上面引用的参考文献一样。

相关问题