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

Clang拒绝含涉及类自身的requires子句的模板构造函数类外定义是否合规?

Clang拒绝含自身类型requires子句的模板构造函数是否符合C++标准?

问题重现

首先看一段可正常编译的、类外定义模板构造函数的结构体代码:

template <typename T>
struct Foo {
  template <typename F>
  Foo(F f);
};

template <typename T>
template <typename F>
Foo<T>::Foo(F f) {}

在-std=c++20标准下,Clang可正常编译这段代码。但当为模板构造函数添加涉及结构体自身类型的requires子句后,Clang会报错,而GCC可正常接受:

报错代码示例:

#include <concepts>

template <typename T>
struct Foo {
  template <typename F>
    requires (!std::same_as<Foo<T>, int>)
  Foo(F f);
};

template <typename T>
template <typename F>
  requires (!std::same_as<Foo<T>, int>)
Foo<T>::Foo(F f) {}

Clang报错信息:

<source>:13:9: error: out-of-line definition of 'Foo<T>' does not match any declaration in 'Foo<T>'
Foo<T>::Foo(F f) {}
        ^~~

核心疑问

Clang拒绝此代码是否符合C++标准?若符合,标准中哪一部分对此有规定?

补充背景:添加涉及待构造类型的requires子句,是为了区分构造函数与移动构造函数,避免当F与Foo类型相同时,后续requires表达式因递归依赖无法求值。实际代码更复杂,且接受F的转发引用。

解答

Clang的行为不符合C++标准,GCC的处理是正确的。

根据C++20标准中[temp.spec.match](即13.7.6.1节,模板声明与定义的匹配)的规定:类模板的成员模板的类外定义,其模板参数列表、requires子句等必须与类内声明实质等价。此处类内声明和类外定义的requires子句完全一致,都是!std::same_as<Foo<T>, int>,不存在实质差异,应当被视为匹配。

Clang此处的报错属于编译器实现层面的问题,未能正确处理requires子句中引用类模板自身实例化类型的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 11:56:45