简体   繁体   中英

std::list<std::unique_ptr>: empty initializer list vs. default constructor

The code

#include <list>
#include <memory>

class B;
class A {
    std::list<std::unique_ptr<B>> bs;
public:
    A();
    ~A();
};

int main()
{
    A x;
    return 0;
}

obviously compiles. It doesn't link because A::A() and A::~A() are missing, but that is expected and alright. Changing

std::list<std::unique_ptr<B>> bs;

which is supposed to call the std::list 's standard constructor

list() : list(Allocator()) {}

(C++14 and up) to

std::list<std::unique_ptr<B>> bs{};

which is supposed to call list(std::initializer_list, const Allocator & = Allocator()); the default constructor too. (Thanks to Nicol Bolas , who rightly referred to [over.match.list] 13.3.1.7) gives the following error with c++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010 and the --std=c++17 parameter:

/usr/include/c++/5/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]’:
/usr/include/c++/5/bits/unique_ptr.h:236:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]’
/usr/include/c++/5/bits/stl_list.h:106:12:   required from ‘void __gnu_cxx::new_allocator<_Tp>::destroy(_Up*) [with _Up = std::_List_node<std::unique_ptr<B> >; _Tp = std::_List_node<std::unique_ptr<B> >]’
/usr/include/c++/5/bits/list.tcc:75:4:   required from ‘void std::__cxx11::_List_base<_Tp, _Alloc>::_M_clear() [with _Tp = std::unique_ptr<B>; _Alloc = std::allocator<std::unique_ptr<B> >]’
/usr/include/c++/5/bits/stl_list.h:446:17:   required from ‘std::__cxx11::_List_base<_Tp, _Alloc>::~_List_base() [with _Tp = std::unique_ptr<B>; _Alloc = std::allocator<std::unique_ptr<B> >]’
/usr/include/c++/5/bits/stl_list.h:507:11:   required from here
/usr/include/c++/5/bits/unique_ptr.h:74:22: error: invalid application of ‘sizeof’ to incomplete type ‘B’
  static_assert(sizeof(_Tp)>0,
                      ^

Which barks about the type of B being incomplete. My question is:

Why does the initializer_list constructor need the complete type of B for an empty initializer list?

Pointers to the relevant parts of the standard are always appreciated.

I think you've stepped onto the bleeding edge .

This appears to be an active issue on the CWG (Core Working Group on the C++ committee).

CWG 1396 appears to be concerned with this very issue. This issue links to CWG 1360 which says in part:

The problem is exacerbated with class templates, since the current direction of CWG is to instantiate member initializers only when they are needed (see issue 1396).

In your example, the initializer of bs is never needed, and thus by the "direction" referred to above, should never be instantiated. We just aren't there yet today. Both of these issues have status drafting , meaning: they're working on it.

FWIW, VS-2015 as reported at http://webcompiler.cloudapp.net compiles (but of course does not link) this example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM