You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

默认模板实参成员访问异常:是否属于Clang的编译BUG?

问题背景

我们来看两个C++模板相关示例:

示例1

struct A{
    template<class T, int R>
    friend void show();

private:
    int c;
};

template<class T, int R = decltype(T{}.c){0} >
void show(){
}

int main(){
  show<A>();
}

示例2

struct A{
    template<class T, int R>
    friend void show();

private:
    int c;
};

template<class T, int R = decltype(A{}.c){0} >
void show(){
}

int main(){
    show<A>();
}

Clang编译表现

Clang接受示例2但拒绝示例1,报错信息如下:

<source>:14:3: error: no matching function for call to 'show'
  show<A>();
  ^~~~~~~
<source>:10:6: note: candidate template ignored: substitution failure [with T = A, R = 0]: 'c' is a private member of 'A'
void show(){
     ^
1 error generated.
ASM generation compiler returned: 1
<source>:14:3: error: no matching function for call to 'show'
  show<A>();
  ^~~~~~~
<source>:10:6: note: candidate template ignored: substitution failure [with T = A, R = 0]: 'c' is a private member of 'A'
void show(){
     ^

结论与分析

你观察到的Clang对示例1的拒绝属于编译器Bug,不存在额外的C++标准规则支持这种差异处理,具体依据如下:
你引用的标准条款完全适用:

默认模板实参的访问权限在其声明所在上下文检查,而非在任何使用点检查。
所有访问控制规则影响从特定实体声明中命名类成员的权限,包括待声明实体名称之前的声明部分;如果实体是类,还包括出现在类成员说明之外的类成员定义。
两个示例的唯一差异是默认模板实参中访问c的对象类型是否依赖模板参数:

  • 示例2的默认实参直接使用A{}.c,Clang在show的声明上下文正确识别了show是A的友元,允许访问私有成员c,符合标准要求。
  • 示例1的默认实参使用依赖模板参数的T{}.c,Clang错误地将访问权限检查推迟到了模板实例化的使用点(也就是main函数中调用show<A>()的上下文),而main函数没有A的私有成员访问权限,因此抛出了错误,这违背了标准中默认模板实参访问权限仅在声明上下文检查的规定。
    友元的访问权限覆盖整个函数声明的所有部分,包括模板参数列表、默认实参,和函数是否为模板、实参是否依赖模板参数无关。目前GCC、MSVC均能正确接受这两个示例,仅Clang存在该实现缺陷。

内容的提问来源于stack exchange,提问作者xmh0511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 04:27:04