使用requires子句禁用非法拷贝构造函数失效问题
代码在Clang编译通过但GCC失败的原因分析
先看你提供的代码:
#include <cstdint> template <std::size_t N> struct foo { foo(foo<0> other) requires (N != 0) {} }; int main() {}
问题核心在于C++标准对类模板成员声明的检查规则,以及GCC和Clang的实现差异:
- 当实例化
foo<0>时,编译器会扫描类内所有成员的声明——即使某个成员函数的requires约束不满足,编译器仍需检查该成员声明本身的合法性,而非直接忽略整个函数。 - 你的构造函数参数是
foo<0> other(按值传递),而按值传递参数要求对应的类型是完全类型(编译器需要知道对象大小才能分配栈空间)。但此时foo<0>正处于类模板实例化过程中,类定义还未完成,属于不完全类型。 - Clang的实现逻辑是:既然该构造函数的约束
N!=0在N=0时不成立,这个函数永远不会被实例化,因此跳过了对参数类型完全性的严格检查;而GCC严格遵循标准中“类模板成员声明必须合法”的要求,即使约束不满足,也会检查声明的类型合法性,发现foo<0>作为不完全类型用于按值传参,因此抛出错误。
可以做个验证:如果把参数改成引用类型foo<0>& other,引用不需要类型是完全类型,此时GCC也能正常编译通过,这就印证了问题的根源是按值传参对完全类型的要求。
内容的提问来源于stack exchange,提问作者Orbit
相关产品推荐
相关产品推荐

