前向声明类的unique_ptr的C++11容器

C++11 container of unique_ptr of forward declared class

本文关键字:ptr C++11 容器 unique 声明      更新时间:2023-10-16

g++ -std=c++11不编译包含容器的类,该容器包含指向前向声明类的唯一指针。问题:

  • 为什么
  • 有合理的变通办法吗

代码示例:

#include <vector>
#include <memory>
// variant 1 (with full class definition): compiles
class Bar { [..] }; 
using BarPtr = std::unique_ptr<Bar>;
// variant 2 (with shared instead of unique pointers): compiles
using BarPtr = std::shared_ptr<class Bar>;
// variant 0 (which is what we want): compilation fails below
using BarPtr = std::unique_ptr<class Bar>;
// end of variants
class Foo {
    std::vector<BarPtr> vec;
 public:
    Foo() {} // compilation of variant 0 fails here:
             // In instantiation of ‘void std::default_delete<Bar>::operator()(Bar*) const
             // ... 
             // invalid application of ‘sizeof’ to incomplete type ‘Bar’
};

我已经看过如何转发声明要在unique_ptr和Is std::unique_ptr<的标准容器中使用的类;T>需要知道T?的完整定义?,但对于我的上述问题,没有找到令人信服的答案。

您需要将Foo的这些部分移动到实现文件中,该文件需要完整的Bar定义(请参阅Howard Hinnant的表:https://stackoverflow.com/a/6089065/2173029)。根据本指南,编制:

#include <vector>
#include <memory>
class Bar;
using BarPtr = std::unique_ptr<Bar>;
class Foo {
    std::vector<BarPtr> vec;
 public:
    Foo(); // Needs Bar in implementation
    ~Foo();// Needs Bar in implementation
};

您可以这样做:

#include <vector>
#include <memory>
class Bar;
using BarPtr = std::unique_ptr<Bar>;
class Foo {
    std::vector<BarPtr> vec;
 public:
    Foo() {} // variant 3 fails here:
             // invalid application of ‘sizeof’ to incomplete type ‘Bar’
};

//Implementation goes here
class Bar{};
int main(){
    Foo a;
}

实时演示

问题是不能通过指向不完整(正向声明)类型的指针进行删除。确保Bar的定义在包含类的析构函数中可见,或者为看到它的unique_ptr使用自定义deleter。另请参阅具有不完整类型won';t编译

行的错误消息

Foo() {};

似乎表明需要一个析构函数~Bar()。但为什么呢?我的这部分问题仍然悬而未决。

然而,对于实际的解决方案,答案很简单:用替换上面的行

Foo();

并且在看到类CCD_ 6的完整定义的编译单元中实现CCD_。