[英]Different results between clang/gcc and MSVC for templated constructor in base class
I stumbled over the following piece of code.我偶然发现了以下一段代码。 The
"DerivedFoo"
case produces different results on MSVC than on clang or gcc. "DerivedFoo"
案例在 MSVC 上产生的结果与在 clang 或 gcc 上不同。 Namely, clang 13 and gcc 11.2 call the copy constructor of Foo
while MSVC v19.29 calls the templated constructor.即,clang 13 和 gcc 11.2 调用
Foo
的复制构造函数,而 MSVC v19.29 调用模板化构造函数。 I am using C++17.我正在使用 C++17。
Considering the non-derived case ( "Foo"
) where all compilers agree to call the templated constructor, I think that this is a bug in clang and gcc and that MSVC is correct?考虑到所有编译器都同意调用模板构造函数的非派生案例(
"Foo"
),我认为这是 clang 和 gcc 中的一个错误,并且 MSVC 是否正确? Or am I interpreting things wrong and clang/gcc are correct?还是我解释错了,而 clang/gcc 是正确的? Can anyone shed some light on what might be going on?
任何人都可以阐明可能发生的事情吗?
Code ( https://godbolt.org/z/bbjasrraj ):代码( 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);
}
Result for clang and gcc: 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
Result for MSVC: 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
It is correct that the constructor template is generally a better match for the constructor call with argument of type DerivedFoo&<\/code> or
Foo&<\/code> than the copy constructors are, since it doesn't require a
const<\/code> conversion.
构造函数模板通常比复制构造函数更适合使用
DerivedFoo&<\/code>或
Foo&<\/code>类型的参数的构造函数调用,因为它不需要
const<\/code>转换。
However, [over.match.funcs.general]\/8<\/a> essentially (almost) says, in more general wording, that an inherited constructor that would have the form of a move or copy constructor is excluded from overload resolution, even if it is instantiated from a constructor template.然而,
[over.match.funcs.general]\/8<\/a>基本上(几乎)用更一般的措辞表示,具有移动或复制构造函数形式的继承构造函数被排除在重载决议之外,即使它被实例化从构造函数模板。 Therefore the template constructor will not be considered.
因此将不考虑模板构造函数。
DerivedFoo d2(d1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.