【发布时间】:2019-04-20 03:33:08
【问题描述】:
最近学习了智能ptrs,我正在尝试编写一个返回unique_ptrs的工厂函数。在阅读了几篇关于将创建时间与明确定义的 ctor 和 dtor 放在同一个 cpp 文件中的文章后,我想我可以这样做:
// factory.hpp
struct Foo;
std::unique_ptr<Foo> create();
// foo.cpp
struct Foo {
Foo();
~Foo();
Foo(const Foo &);
Foo(Foo &&);
};
std::unique_ptr<Foo> create() {
return make_unique<Foo>();
}
#include "factory.hpp"
int main() {
auto r = create();
return 0;
}
但是我收到了不完整的类型错误。然后经过几个小时的网络搜索和实验, 我意识到我什至不能这样做:
这是经典的 unique_ptr Pimpl 习语。
// A.hpp
struct B;
struct A {
A();
~A();
unique_ptr<B> b;
};
// A.cpp
struct B {};
A::A() = default;
A::~A() = default;
#include "A.hpp"
int main() {
A a; // this is fine since we are doing the Pimpl correctly.
// Now, I can't do this.
auto b = std::move(a.b); // <--- Can't do this.
return 0;
}
为了讨论,请忽略std::move 行毫无意义的事实。
我得到了同样的不完整类型错误。
以上两种情况本质上是一样的。经过一番搜索,我想我明白了错误背后的原因, 但我想要一些指示(双关语)和你们的确认。
- 删除不完整的类型是UB。这就是为什么禁止使用默认删除器创建具有不完整类型的 unique_ptrs。
- 如果我使用自定义删除器,我应该能够做到这一点。
- 我猜是因为在我的情况下我使用的是默认删除器,所以由于某种我不太确定的原因,我无法完成。
明确定义创建和销毁函数应该可以解决问题。但对我来说,这很丑陋。一方面,我的情况是默认删除器。
另一方面,在我看来,我不能使用 lambda 作为销毁器,因为 lambda 的类型只有编译器知道,
我不能用decltype 做我的工厂函数声明。
所以我的问题是:
- 这次失败的原因是什么?
- 编写返回 unique_ptrs 的工厂函数的正确方法是什么?
如果我说的有问题,请纠正我。任何指针将不胜感激。
【问题讨论】:
-
您在 factory.hpp 中声明了
create,然后在 foo.hpp 中定义了create(作为非内联函数)。那里发生了什么? -
@Kerndog73 抱歉,打错了。已编辑。应该是一个cpp文件。
标签: c++ c++11 smart-pointers forward-declaration