I stumbled over the following piece of code. The "DerivedFoo"
case produces different results on MSVC than on clang or gcc. Namely, clang 13 and gcc 11.2 call the copy constructor of Foo
while MSVC v19.29 calls the templated constructor. I am using 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? Or am I interpreting things wrong and clang/gcc are correct? Can anyone shed some light on what might be going on?
Code (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:
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:
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-
and got the above results (i.e. MSVC calls the templated constructor), both in C++17 and C++20. I used VS2019 (cl.exe in version 19.29.30139). – Jacobsen