std::list<std::unique_ptr>:空初始化列表与默认构造函数

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

代码

#include <list>
#include <memory>

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

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

显然可以编译。它不会 link 因为 A::A()A::~A() 丢失了,但这是意料之中的。改变

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

应该调用 std::list 的标准构造函数

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

(C++14 及更高版本)至

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

应该调用 list(std::initializer_list, const Allocator & = Allocator()); 默认构造函数也是。 (感谢 Nicol Bolas,他正确地提到了 [over.match.list] 13.3.1.7) 使用 c++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010--std=c++17[=45 给出以下错误=]参数:

/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,
                      ^

B 的类型不完整。我的问题是:

为什么 initializer_list 构造函数需要 B 的完整类型作为空的初始化列表?

始终感谢指向标准相关部分的指针。

我想你已经踏上了 bleeding edge

这似乎是 CWG(C++ 委员会核心工作组)中的一个活跃问题。

CWG 1396 appears to be concerned with this very issue. This issue links to CWG 1360 部分表示:

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).

在您的示例中,bs 的初始值设定项 从不需要 ,因此根据上面提到的 "direction", 应该 永远不会被实例化。我们今天还没有。这两个问题的状态都是 drafting,意思是:他们正在处理它。

FWIW,http://webcompiler.cloudapp.net 报告的 VS-2015 编译(但当然不会 link)这个例子。