不完整的类型的应用无效。

发布于 2025-02-04 04:25:35 字数 2280 浏览 4 评论 0原文

请首先查看目录结构[问题结束的底部]。

以下是我的cmake文件:

  1. 主cmake

      cmake_minimum_required(版本3.9)  
     set(cmake_cxx_standard 14)
    
     add_executable(test main.cc)  
    
     target_include_directories(测试public test_include_interface)
    
     target_link_libraries(测试public test_test)
     
  2. 测试CMAKE:

      add_library(test_include_interface接口)
    
     target_include_directories(test_include_interface接口$ {cmake_current_source_dir})
    
     add_library(test_test static test_interface.h
                                         test.h
                                         test.cc)
    
     target_include_directories(test_test接口$ {cmake_current_source_dir})
     

test.h

#pragma once

#include "test_interface.h"

#include <memory>

class Test : public ITest {
public:
    Test();

private:
    class Impl;
    std::unique_ptr<Impl> impl_;

};

test.cc

#include "test.h"


class Test::Impl {
public:
    Impl() {}
    ~Impl() {}
};

Test::Test() : impl_{std::make_unique<Impl>()} {}

错误:

In file included from /usr/include/c++/9/memory:80,
                 from /home/vkd0726/test/test/test.h:9,
                 from /home/vkd0726/test/main.cc:2:
/usr/include/c++/9/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Test::Impl]’:
/usr/include/c++/9/bits/unique_ptr.h:292:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Test::Impl; _Dp = std::default_delete<Test::Impl>]’
test/test/test.h:11:7:   required from here
/usr/include/c++/9/bits/unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘Test::Impl’
   79 |  static_assert(sizeof(_Tp)>0,
      |                ^~~~~~~~~~~
make[2]: *** [CMakeFiles/test.dir/build.make:63: CMakeFiles/test.dir/main.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

请帮助我了解此错误以及如何解决该错误? CMAKE或代码本身是一个问题。我已经在许多地方看到了这种“ IMPH”设计模式使用,但无法编写测试片段。这里怎么了?

目录结构

“目录结构”

Please have a look at directory structure first [ attached at the bottom of the question end].

Following are my Cmake files :

  1. Main cmake

     cmake_minimum_required(VERSION 3.9)  
     set (CMAKE_CXX_STANDARD 14)
    
     add_executable (test main.cc)  
    
     target_include_directories(test PUBLIC test_include_interface)
    
     target_link_libraries(test PUBLIC test_test)
    
  2. Test cmake :

     add_library(test_include_interface INTERFACE)
    
     target_include_directories(test_include_interface INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
    
     add_library(test_test STATIC test_interface.h
                                         test.h
                                         test.cc)
    
     target_include_directories(test_test INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
    

test.h

#pragma once

#include "test_interface.h"

#include <memory>

class Test : public ITest {
public:
    Test();

private:
    class Impl;
    std::unique_ptr<Impl> impl_;

};

test.cc

#include "test.h"


class Test::Impl {
public:
    Impl() {}
    ~Impl() {}
};

Test::Test() : impl_{std::make_unique<Impl>()} {}

Error :

In file included from /usr/include/c++/9/memory:80,
                 from /home/vkd0726/test/test/test.h:9,
                 from /home/vkd0726/test/main.cc:2:
/usr/include/c++/9/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Test::Impl]’:
/usr/include/c++/9/bits/unique_ptr.h:292:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Test::Impl; _Dp = std::default_delete<Test::Impl>]’
test/test/test.h:11:7:   required from here
/usr/include/c++/9/bits/unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘Test::Impl’
   79 |  static_assert(sizeof(_Tp)>0,
      |                ^~~~~~~~~~~
make[2]: *** [CMakeFiles/test.dir/build.make:63: CMakeFiles/test.dir/main.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Please help me understand this error and how to resolve it ? Is it a problem with the Cmake or code itself. I have seen such "Impl" design pattern use at many places but unable to write a test snippet. What is wrong here ?

Directory structure

Directory structure

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

在你怀里撒娇 2025-02-11 04:25:35

test不包含用户定义的破坏者,因此编译器会生成此驱动器的隐藏版本。由于该驱动器涉及逻辑以删除test :: impl对象当std :: simory_ptr&lt; test :: strime_ptr&test :: strand&gt;被调用时,您会收到编译器的错误抱怨。

您可以通过在test.cc中定义驱动器来解决此问题:

test.h

#include <memory>

class Test : public ITest {
public:
    Test();
    ~Test(); // new
private:
    class Impl;
    std::unique_ptr<Impl> impl_;

};

test.cc

class Test::Impl {
...
};

...

Test::~Test() = default;

The Test does not contain a user defined destructor, so the compiler generates a inlined version of this destructor. Since this destructor involves logic to delete the Test::Impl object when the destructor of std::unique_ptr<Test::Impl> is invoked, you get the error your compiler complains about.

You can fix this by defining the destructor in test.cc:

test.h

#include <memory>

class Test : public ITest {
public:
    Test();
    ~Test(); // new
private:
    class Impl;
    std::unique_ptr<Impl> impl_;

};

test.cc

class Test::Impl {
...
};

...

Test::~Test() = default;
自由如风 2025-02-11 04:25:35

这是一个常见的问题,与std :: simel_ptr for pimpl 。正如@fabian提到的主要方法是提供声明FIR嵌套类的驱动器,并在与 pimpl 实现的同一翻译单元中定义它(最有可能是默认函数)。但是,由于编译器无法推断出嵌套类的损坏器的微不足道(根据OP,test),这种方法可能会禁用某些角案例的优化。另一种方法是为std :: simolor_ptr提供A deleter 类,然后将嵌套类的destructor完好无损:

class test{
public:
    test();
private:
    class impl;
    struct deleter{
        void operator(impl *)const;
    };
    std::unique_ptr<impl, deleter> up_impl;
};

现在在相同的翻译中定义Deleter的函数调用操作员单位为Ingl:

void test::deleter::operator(test::impl * ptr) const
    { delete ptr; };

这看起来还有更多的工作。但是它以隐式定义的驱动器有效。它还更好地适合0/3/5的规则。

This is a common problem faced with std::unique_ptr for pimpl. The primary approach would be - as @fabian mentioned - to provide a declaration fir the nesting class's destructor and define it in the same translation unit as the pimpl implementation (most probably as a defaulted function). But this approach might disable some corner case optimizations, due to compiler not being able to deduce the triviality of the destructor of nesting class(Test according to OP). Another approach would be to provide a deleter class for the std::unique_ptr and leave the nesting class`s destructor intact:

class test{
public:
    test();
private:
    class impl;
    struct deleter{
        void operator(impl *)const;
    };
    std::unique_ptr<impl, deleter> up_impl;
};

Now define the deleter's function call operator in the same translation unit as impl to:

void test::deleter::operator(test::impl * ptr) const
    { delete ptr; };

This looks a little more work. But it pays off with an implicitly defined destructor. It also better suits the rule of 0/3/5.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文