首页 > 解决方案 > 哪些存储类型不完整的 STL 数据结构可以用作类成员?

问题描述

据我所知,从 C++17 开始,一些 STL 数据结构可能会以不完整的类型“存在”作为描述存储类型的模板参数。例如,如果类的所有属性(需要定义)都在单独的 .cpp 文件中实现,我可以使用std::unique_ptr<Incomplete>(我不确定它是否是数据结构)或作为类成员:std::vector<Incomplete>Incomplete

class Incomplete;
using Complete = int;
class Foo {
private:
  std::unique_ptr<Incomplete> u_p;
  std::vector<Incomplete> v;
  std::deque<Incomplete> d;
  std::list<Incomplete> l;
  std::set<Incomplete> s;
  std::unordered_map<Complete, Complete> u_m_cc;
  std::unordered_map<Complete, Incomplete> u_m_ci;
  std::unordered_map<Incomplete, Complete> u_m_ic;
  std::unordered_map<Incomplete, Incomplete> u_m_ii;
public:
  // implemented in a separate .cpp which has Incomplete defined:
  Foo();
  Foo(Foo&&);
  Foo& operator=(Foo&&);
  Foo(Foo const&);
  Foo& operator=(Foo const&);
  ~Foo();
};

那么,上面列出的哪些数据成员对这种用法有效?其他数据结构、智能指针等呢?

标签: c++stlc++17standardsforward-declaration

解决方案


假设在类型完成之前没有显式或隐式使用任何类成员:

从 C++11 开始,模板参数总是不完整的std::unique_ptr,请分别参见[unique.ptr]/5[util.smartptr.shared]/2std::shared_ptr

N4510到 C++17添加了对容器中不完整类型的支持,但仅适用于

std::vector
std::list
std::forward_list

并且仅当使用的分配器满足分配器完整性要求时,即即使值类型本身不完整,分配器类型X本身也是完整类型,所有成员也是如此std::allocator_traits<X>,除了::value_type. 默认分配器std::allocator满足这些要求。

其他容器都不能与不完整类型一起使用。根据上面链接的提案,范围仅限于这三个容器“作为第一步”,因为主要实现已经支持它。


推荐阅读