当前位置: 首页 > 知识库问答 >
问题:

不完整向量类型(C 17)的编译错误

宗政欣可
2023-03-14

首先是一些背景。正如C 17标准所述:

[vector.overview]/3如果分配器满足分配器完整性要求17.6,则在实例化vector时可使用不完整类型T。3.5.1.T应在引用向量的任何结果特化成员之前完成。

我在本回购协议中尝试了3种方案(代码复制在底部):

  • 包含不完整向量类型的类在同一头文件中声明(默认ctor/dtor)并定义
  • 编译用b. h包括:clangtest.cppb.cpp--std=c 17
  • 编译用b. h包括:clangtest.cppc.cpp--std=c 17

我的问题是,为什么在第二种情况下汇编失败,而在第一种或第三种情况下汇编失败?如果正如标准所说的,引用了std::vector的一个成员,那么为什么在仅标题的情况下不引用它呢?这个被引用的成员是什么?有没有什么方法可以让第二个案例在不涉及默认关键字或转发声明的情况下进行编译?

main。cpp

// #include "a.h" // << OK
#include "b.h" // << Compile error
// #include "c.h" // << OK

int main(int argc, char const *argv[])
{
    Bar b;
    return 0;
}

a.h

#include <vector>

struct Foo;

struct Bar
{
    Bar() = default;
    virtual ~Bar() = default;
    std::vector<Foo> foos;
};

struct Foo
{
};

b.h

#include <vector>
struct Foo;
struct Bar
{
    Bar() = default;
    ~Bar() = default;
    std::vector<Foo> foos;
};

b.cpp

#include "b.h"
struct Foo
{
};

c.h

#include <vector>

struct Foo;
struct Bar
{
    Bar();
    ~Bar();
    std::vector<Foo> foos;
};

c.cpp

#include "c.h"

struct Foo
{
};

Bar::Bar(){}
Bar::~Bar(){}

错误案例的编译输出:

(py3) cpp/vector_incomplete > clang++ test.cpp b.cpp --std=c++17
In file included from test.cpp:2:
In file included from ./b.h:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:427:68: error: 
      arithmetic on a pointer to an incomplete type 'Foo'
        __alloc_traits::destroy(__alloc(), _VSTD::__to_raw_pointer(--__soon_to_be_end));
                                                                   ^ ~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:370:29: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::__destruct_at_end' requested here
    void clear() _NOEXCEPT {__destruct_at_end(__begin_);}
                            ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:464:9: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::clear' requested here
        clear();
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:496:5: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::~__vector_base' requested here
    vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
    ^
./b.h:6:5: note: in instantiation of member function 'std::__1::vector<Foo, std::__1::allocator<Foo> >::vector' requested here
    Bar() = default;
    ^
./b.h:3:8: note: forward declaration of 'Foo'
struct Foo;
       ^
In file included from test.cpp:2:
In file included from ./b.h:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:275:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference:16:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:644:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1817:55: error: 
      invalid application of 'sizeof' to an incomplete type 'Foo'
        {_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));}
                                                      ^~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1555:14: note: in
      instantiation of member function 'std::__1::allocator<Foo>::deallocate' requested here
        {__a.deallocate(__p, __n);}
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:465:25: note: in
      instantiation of member function 'std::__1::allocator_traits<std::__1::allocator<Foo> >::deallocate' requested here
        __alloc_traits::deallocate(__alloc(), __begin_, capacity());
                        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:496:5: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::~__vector_base' requested here
    vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
    ^
./b.h:6:5: note: in instantiation of member function 'std::__1::vector<Foo, std::__1::allocator<Foo> >::vector' requested here
    Bar() = default;
    ^
./b.h:3:8: note: forward declaration of 'Foo'
struct Foo;
       ^
In file included from test.cpp:2:
In file included from ./b.h:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:373:52: error: 
      arithmetic on a pointer to an incomplete type 'Foo'
        {return static_cast<size_type>(__end_cap() - __begin_);}
                                       ~~~~~~~~~~~ ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:465:57: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::capacity' requested here
        __alloc_traits::deallocate(__alloc(), __begin_, capacity());
                                                        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:496:5: note: in
      instantiation of member function 'std::__1::__vector_base<Foo, std::__1::allocator<Foo> >::~__vector_base' requested here
    vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
    ^
./b.h:6:5: note: in instantiation of member function 'std::__1::vector<Foo, std::__1::allocator<Foo> >::vector' requested here
    Bar() = default;
    ^
./b.h:3:8: note: forward declaration of 'Foo'
struct Foo;
       ^
In file included from test.cpp:2:
In file included from ./b.h:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:873:54: error: 
      arithmetic on a pointer to an incomplete type 'const std::__1::vector<Foo, std::__1::allocator<Foo> >::value_type'
      (aka 'const Foo')
      __annotate_contiguous_container(data(), data() + capacity(),
                                              ~~~~~~ ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:552:9: note: in
      instantiation of member function 'std::__1::vector<Foo, std::__1::allocator<Foo> >::__annotate_delete' requested here
        __annotate_delete();
        ^
./b.h:6:5: note: in instantiation of member function 'std::__1::vector<Foo, std::__1::allocator<Foo> >::~vector' requested here
    Bar() = default;
    ^
./b.h:3:8: note: forward declaration of 'Foo'
struct Foo;
       ^
4 errors generated.

共有2个答案

孟宏才
2023-03-14

它会失败,因为您已经默认了构造函数和析构函数,这意味着实现在每个编译单元中,就像您编写的那样。

struct Bar
{
    Bar() {}
    ~Bar() {}
    std::vector<Foo> foos;
};

然后编译器需要知道Foo的大小,并希望调用其析构函数。

但是如果您将函数的实现带到中。cpp并且只有在标题中有声明,您才能保存编译main。cpp因为编译器需要知道的一切都在那里。

您还可以(我建议)默认c.cpp中的函数:

#include "c.h"

struct Foo
{
};

Bar::Bar() = default;
Bar::~Bar() = default;
申黎明
2023-03-14

包括b. h是行不通的。在std::向量模板中的某个地方将有一行为NUM*sizeof(Foo)分配内存。如果您在源文件中隐藏了Foo的定义,那么Foo的大小将是未知的,编译将失败。

 类似资料:
  • 我在Eclipse中编写代码,有如下内容: 但是,当我尝试构建时,会出现以下错误: 有什么想法吗?我在谷歌上搜索过,似乎大多数有这个问题的人根本没有包含正确的头文件,我相信我做得是正确的。

  • 我正在开发一个代理适配器,使用Java中的泛型将一个请求/响应转换为另一个请求/响应。 我有一个接口: 适配器的实现(仅以请求案例为例): 抽象类: 从Java中的泛型类型推断泛型类型(编译时错误) 我在那个问题上花了大约三天时间。有什么想法吗?谢了。

  • 考虑这个代码,有一个明显的编译错误:(1) 使用也不会有任何帮助:(2) 然后(令我大吃一惊)我发现,这将编译:(3) 然后我检查了一下,这是否也有助于——否:(4) 我认为它与s有关,事实上:在中包装,编译:(5) 为了完整起见,删除的定义会再次引发一个错误:(6) 这是怎么回事?据我所知,编译器必须知道的大小/定义才能分配它,因此仅仅声明它是不够的。此外,我认为,定义必须先于分配。 这似乎是正

  • 问题内容: 我在写一些代码,遇到编译错误。这就是我所拥有的: 我以为使用继承时没有正确声明泛型,所以我检查了Oracle的教程,他们在其中编写 上面的声明使用相同的泛型类型,这是我在示例中要完成的工作。似乎假设from 与from 有所不同。否则,它应该能够 将 两者 合并并看到相同的类型。如何正确实现我要实现的目标? ( 即,某物的常量是某物的值,这是同一物的表达 ) 问题答案: 您的变量定义为

  • 问题内容: 我已经下载了一些用Java编写的开源软件,并尝试使用Eclipse进行编译。我收到错误:在某些文件中, “类名”类型的层次结构不一致 。是什么导致这些错误,我该如何解决? 问题答案: 这意味着您正在尝试实现一个不存在的接口,或者您正在扩展一个不存在的类。 尝试刷新您的Eclipse。 如果不起作用,则可能意味着您引用了不在构建路径中的JAR。检查项目的类路径,并验证其中是否包含接口或类