【发布时间】:2022-02-06 18:25:15
【问题描述】:
我偶然发现了以下代码。 "DerivedFoo" 案例在 MSVC 上产生的结果与在 clang 或 gcc 上不同。即,clang 13 和 gcc 11.2 调用 Foo 的复制构造函数,而 MSVC v19.29 调用模板化构造函数。我正在使用 C++17。
考虑到所有编译器都同意调用模板化构造函数的非派生情况("Foo"),我认为这是 clang 和 gcc 中的错误,MSVC 是否正确?还是我解释错了,而 clang/gcc 是正确的?谁能解释一下可能发生了什么?
代码(https://godbolt.org/z/bbjasrraj):
#include <iostream>
using namespace std;
struct Foo {
Foo() {
cout << "\tFoo default constructor\n";
}
Foo(Foo const &) { cout << "\tFoo COPY constructor\n";
}
Foo(Foo &&) {
cout << "\tFoo move constructor\n";
}
template <class U>
Foo(U &&) {
cout << "\tFoo TEMPLATED constructor\n";
}
};
struct DerivedFoo : Foo {
using Foo::Foo;
};
int main() {
cout << "Foo:\n";
Foo f1;
Foo f2(f1);
cout << "\nConst Foo:\n";
Foo const cf1;
Foo cf2(cf1);
cout << "\nDerivedFoo:\n";
DerivedFoo d1;
DerivedFoo d2(d1);
cout << "\nConst DerivedFoo:\n";
DerivedFoo const cd1;
DerivedFoo cd2(cd1);
}
clang 和 gcc 的结果:
Foo:
Foo default constructor
Foo TEMPLATED constructor
Const Foo:
Foo default constructor
Foo COPY constructor
DerivedFoo:
Foo default constructor
Foo COPY constructor <<<<< This is different
Const DerivedFoo:
Foo default constructor
Foo COPY constructor
MSVC 的结果:
Foo:
Foo default constructor
Foo TEMPLATED constructor
Const Foo:
Foo default constructor
Foo COPY constructor
DerivedFoo:
Foo default constructor
Foo TEMPLATED constructor <<<<< This is different
Const DerivedFoo:
Foo default constructor
Foo COPY constructor
【问题讨论】:
-
如果您使用 /permissive- 选项来强制符合 c++17,则 MSVC 行为正常。看起来像是旧代码的保留,可能会被符合标准的编译器破坏。
-
@doug 这些行为(未经许可)是否公开记录?
-
不知道该特定问题是否已解决。 Microsoft 有一长串合规性差异以及如何升级旧代码。
-
@doug 我在 MSVC 中使用
/permissive-编译了代码,并在 C++17 和 C++20 中得到了上述结果(即 MSVC 调用模板化构造函数)。我用的是VS2019(19.29.30139版本的cl.exe)。 -
@Sedenion 19.30之前好像没有实现缺陷报告:godbolt.org/z/sjv6h74M4
标签: c++ templates c++17 language-lawyer copy-constructor