c++ - Pimpl - 为什么可以在不完整的类型上调用 make_unique

标签 c++ templates language-lawyer unique-ptr pimpl-idiom

为什么 make_unique 调用会编译? make_unqiue 不要求它的模板参数是一个完整的类型吗?

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

struct F {};

问题源于我的PIMPL实现的“问题”:

我确实理解为什么必须在实现类 (PIMPL) 的 cpp 文件中由用户声明和定义析构函数。

但是移动包含 pimpl- 的类的构造函数仍然可以编译。

class Object
{};

class CachedObjectFactory
{
public:
  CachedObjectFactory();

  ~CachedObjectFactory();
  std::shared_ptr<Object> create(int id) const;

private:
  struct CacheImpl;
  std::unique_ptr<CacheImpl> pImpl;
};

现在是cpp文件:

// constructor with make_unique on incomplete type ?
CachedObjectFactory::CachedObjectFactory()
  : pImpl(std::make_unique<CacheImpl>())
{}

struct CachedObjectFactory::CacheImpl
{
  std::map<int, std::shared_ptr<Object>> idToObjects;
};

//deferred destructor
CachedObjectFactory::~CachedObjectFactory() = default;

有人能解释一下为什么会编译吗? 为什么 build 和破坏之间有区别? 如果析构函数的实例化和default_deleter的实例化有问题,为什么make_unique的实例化没有问题?

最佳答案

make_unique 有多个实例化点:翻译单元的末端也是一个实例化点。您所看到的是编译器仅在 CacheImpl/F 完成后才实例化 make_unique。允许编译器执行此操作。如果您依赖它,则您的代码格式不正确,并且不需要编译器来检测错误。

14.6.4.1 Point of instantiation [temp.point]

8 A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. [...] If two different points of instantiation give a template specialization different meanings according to the one definition rule (3.2), the program is ill-formed, no diagnostic required.

关于c++ - Pimpl - 为什么可以在不完整的类型上调用 make_unique,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52180744/

相关文章:

c++ - 使用 openmp 时奇怪的减速

node.js - Node js swig对象显示

c++ - 这个使用 boost::mismatch 的例子是什么意思?

c++ - 为什么可以使用 operator<=> 比较数组成员,但不能使用独立数组?

c++ - 匹配别名模板作为模板参数

c++ - 为什么在提到纯右值时这里使用术语 "object"?

c++ - 在 C++ 中,如何只使用带有必需参数的长选项?

c++ - 动态分配的矩阵读取不正确

c++ - 小于模板参数的比较

c++ - 如何将一个字符串转换为一长串或另一串 ascii 值?