'Should args to inherited constructors be copied when invoking the base ctor or not?

For the following program:

#include <iostream>

struct Foo
{
    Foo() { std::cout << "Foo()\n"; }
    Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; }
    ~Foo() { std::cout << "~Foo()\n"; }
};

struct A
{
    A(Foo) {}
};

struct B : A
{
    using A::A;
};

int main()
{
    Foo f;
    B b(f);
}

GCC gives:

$ g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Foo()
Foo(const Foo&)
~Foo()
~Foo()

VS 2017 (also in C++17 mode) gives:

Foo()
Foo(const Foo&)
Foo(const Foo&)
~Foo()
~Foo()
~Foo()

Who's right, and why?

(Let's also not forget that VS 2017 doesn't do mandated copy elision properly. So it could just be that the copy is "real" but GCC elides it per C++17 rules where VS doesn't...)



Solution 1:[1]

Elision notwithstanding, it looks to me like Visual Studio is wrong:

[C++17: class.inhctor.init]/1: When a constructor for type B is invoked to initialize an object of a different type D (that is, when the constructor was inherited ([namespace.udecl])), initialization proceeds as if a defaulted default constructor were used to initialize the D object and each base class subobject from which the constructor was inherited, except that the B subobject is initialized by the invocation of the inherited constructor. The complete initialization is considered to be a single function call; in particular, the initialization of the inherited constructor's parameters is sequenced before the initialization of any part of the D object.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1