提问人:Baki 提问时间:4/29/2023 最后编辑:Vlad from MoscowBaki 更新时间:4/29/2023 访问量:134
类构造函数在 clang 上编译,但在 gcc 上被拒绝
Class constructor compiles on clang but rejected on gcc
问:
我正在学习C++中的构造函数。特别是,一个 C++ 类可以有多个构造函数。但后来我制作了以下程序,该程序适用于 clang,但不适用于 gcc 和 msvc。
template<typename T>
struct A {
A() {}
A(A<bool>);
};
A<bool> a; //works with clang but not with gcc and msvc
//A<double> b; //works with all compilers
令人惊讶的是,它仅适用于 clang 并被 gcc 和 msvc 拒绝,但适用于所有 3 个编译器。
MCVC 说道:A<bool> a;
A<double> b;
<source>(4): error C2652: 'A<bool>': illegal copy constructor: first parameter must not be a 'A<bool>'
<source>(4): note: see declaration of 'A<bool>'
<source>(6): note: see reference to class template instantiation 'A<bool>' being compiled
为什么我们会收到此错误,以及根据 C++ 标准哪个编译器是正确的。
答:
1赞
Vlad from Moscow
4/29/2023
#1
根据 C++20 标准(11.4.5.3 复制/移动构造函数)
5 类 X 的构造函数声明格式不正确,如果其 第一个参数是 cv X 类型,没有其他参数 参数,否则所有其他参数都具有默认参数。一个 成员函数模板永远不会实例化以生成这样的 构造函数签名。
因此,当类型模板参数用于模板类的实例化时,实际上您在该类实例化中有以下构造函数bool
A( A );
和错误消息
(4):错误 C2652:“A”:非法复制构造函数:first 参数不能为“A”
指向这个生成的格式错误的复制构造函数,用于类的实例化。A<bool>
另一方面,当类型模板参数是(或其他东西)时,构造函数的这个声明double
A( A<bool> )
对于这样的类实例化不会产生格式错误的复制构造器,因为例如类型和是两个不同的类类型。A<double>
A<bool>
为了避免错误,只需在类模板中将构造函数声明为
template<typename T>
struct A {
A() {}
A(A<bool> &);
};
评论
0赞
user12002570
4/29/2023
A
不是 OP 问题中的类。这是一个类模板。你引用的陈述谈论的是类而不是类模板。
0赞
Vlad from Moscow
4/29/2023
@Jason A<bool> 的实例化是一个类。
0赞
user12002570
4/29/2023
您引用的陈述谈论的是类而不是类模板。
0赞
Vlad from Moscow
4/29/2023
@Jason正如我已经写过的,类模板的实例化是非模板类,不是吗?
0赞
user17732522
4/29/2023
但是,问题在于该规则应该如何应用于模板。这在我看来一点也不明显。从语法上讲,模板的构造函数实际上只有一个声明,而不是每个实例化都有一个声明。
-1赞
user12002570
4/29/2023
#2
程序格式不正确,无需诊断。这可以从 temp.res 中看出:
可以在任何实例化之前检查模板的有效性。 [注意:知道哪些名称是类型名称后,可以以这种方式检查每个模板的语法。 — 尾注 ] 如果出现以下情况,则程序格式不正确,无需诊断:
- 在模板定义之后立即对模板进行假设实例化,由于构造不依赖于模板参数,因此格式不正确,或者
- 在假设实例化中对这种构造的解释与在模板的任何实际实例化中对相应构造的解释不同。...
评论
0赞
HolyBlackCat
4/29/2023
不是我的 -1,但可以说它确实取决于模板参数。
0赞
user12002570
4/29/2023
@HolyBlackCat 但不依赖。A<bool>
1赞
user17732522
4/29/2023
最后突出显示的部分是注释的一部分。它不是规范性的。相关的规范部分是您没有强调的部分,它讨论了实例化之间的差异(其中一个假设在模板定义之后)。假设的实例化是可以的,因为其中不必是完整的。该注释过于宽泛,只是说在应用规则的情况下存在具有该属性的方案,而不是该规则适用于具有该属性的每个方案。A<bool>
A<bool>
0赞
user12002570
4/29/2023
@user17732522 所以你是说它不是IFNDR?由于第一个突出显示的要点,这在我看来是 IFNDR。
0赞
user17732522
4/29/2023
@Jason 要么 [class.copy.ctor] 中的规则不适用,程序格式正确,要么它确实适用于实例化,然后格式不正确,唯一的问题是它是否是 IFNDR。我认为更可能不适用解释确切的措辞,尽管它可能打算适用。我想有人可能会争辩说,从技术上讲,由于非依赖结构,在后一种情况下,假设的实例化格式不正确,因此它是 IFNDR。但我想说,这并不是真的有意为之。[temp.res]/5 在我看来措辞不当。A<bool>
评论
A<bool>
A(A<bool>);