在 gcc 和 msvc 中与特定专业化交友有效,但在 clang 中则不然

问题描述 投票:0回答:1

我想将单一专业作为朋友,如下所示。我用 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); 
}

演示

我有两个问题:

  1. 有没有办法让这个专业化

    void fun2<T>(typename Ext<T>::Inner&);
    成为朋友,以便该程序被所有编译器接受?也就是说,我想要一种解决方法,使这个特定的专业化成为朋友而不是所有
    Ext

  2. 上面显示的程序(在我的帖子中)在 C++20 中格式正确吗?


叮 说:

<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); 
c++ language-lawyer c++20 template-specialization friend
1个回答
0
投票

看来程序是格式错误并且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 是声明中的函数类型或与放置运算符 new 匹配的释放函数的类型,如 [expr.new 中所述]。 扣除按照 [temp.deduct.type] 中的描述进行。

  2. 如果对于如此考虑的一组函数模板,在考虑部分排序([temp.func.order])后没有匹配或有多个匹配,则推导失败,并且在声明情况下,程序格式错误。

(强调我的)

在我们的示例中,该集合是空的,因此没有匹配项,这意味着根据上面引用的参考,该程序的格式不正确。

© www.soinside.com 2019 - 2024. All rights reserved.