Move only class parameter to inherited constructor

The following code does not compile GCC 6.1, but works in Clang 3.8.0and Visual Studio 2015:

#include <memory>

class base {
public:
    base(std::unique_ptr<int>) {}
};

class derived : public base {
public:
    using base::base;
};

int main() {
    derived df(std::make_unique<int>());
}

With the following errors:

main.cpp: In constructor 'derived::derived(std::unique_ptr<int>)':

main.cpp:10:17: error: use of deleted function 
'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) 
[with _Tp = int; _Dp = std::default_delete<int>]'

     using base::base;

                 ^~~~

In file included from /usr/local/include/c++/6.1.0/memory:81:0,

                 from main.cpp:1:

/usr/local/include/c++/6.1.0/bits/unique_ptr.h:356:7: note: declared here

       unique_ptr(const unique_ptr&) = delete;

       ^~~~~~~~~~

main.cpp: In function 'int main()':

main.cpp:14:39: note: synthesized method 'derived::derived(std::unique_ptr<int>)' 
first required here 

     derived df(std::make_unique<int>());

It seems to be trying to call the remote copy constructor, but this works just fine:

void foo(std::unique_ptr<int>) {}

int main() {
    foo(std::make_unique<int>());
}

And this example with -fno-elide-constructorsoutputs move called.:

struct move_only {
    move_only() { std::cout << "default called."; }
    move_only(move_only&&) { std::cout << "move called."; }
};

void foo(move_only) { }

int main() {
    foo(move_only{});
}

I understand that the two situations are not identical, but it seems strange that it &&takes to make an example of an inherited constructor, and not the last. As a health check, explicitly executing move_only(const move_only&) = delete;and changing the signature to void foo(const move_only&) { }is still compiled, except that the move constructor is not even called (possibly, possibly).

12.6.3 from the last draft of the standard states:

1 B D ( , ([namespace.udecl])), D , , , B- . ; , D. [:

struct B1 {
  B1(int, ...) { }
};

// ...

struct D1 : B1 {
  using B1::B1;  // inherits B1(int, ...)
  int x;
  // ...
};

void test() {
  D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
                 // then d.x is default-initialized (no initialization is performed),
  // ...
}

// ...

, foo(move_only) ?

+4
1

( 70972). N4140 [class.inhctor]/8:

, mem-initializer-list, mem-initializer mem-initializer-id, , - , , (12.6.2). , . static_cast<T&&>(p), p - T p.

, , .

+3

All Articles