作为 std::map 成员的不完整类型 [英] incomplete type as member of std::map

查看:46
本文介绍了作为 std::map 成员的不完整类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了与此处所述相同的问题
无法分配具有前向声明值的类std::map 成员变量
在我们的代码库中.

I came about the same issue as described here
Can't allocate class with forward declared value in std::map member variable
in our codebase.

然而,我还发现我们的编译器(MSVC 2017)能够编译它的其他情况...
在摆弄代码之后,我发现定义 con- &cpp 中的析构函数允许文件编译.

Hoever I also found other cases where our compiler (MSVC 2017) is able to compile this...
After fiddling around with the code I found that defining the con- & destructor in the cpp allows the files to compile.

test.h 中:

#ifndef TEST_H
#define TEST_H

#include <map>
struct Incomplete;

class Test {
    std::map<int, Incomplete> member;
public:
    Test();
    ~Test();
    int foo() { return 0; }
};

#endif

test.cpp 中:

#include "test.h"
struct Incomplete {};
Test::Test() {}
Test::~Test() {}

main.cpp中:

#include "test.h"

int main() 
{
    Test test;
    return test.foo();
}

为什么要定义 con- &cpp文件中的析构函数允许member-std::map-variables使用不完整的类型吗?

推荐答案

这是因为声明类成员不需要 Incomplete 完成,而是调用 std::map 析构函数可以,因为它必须调用 Incomplete 析构函数来销毁地图内容.(调用默认的 std::map 构造函数可能需要类型完整,具体取决于实现.我不确定规范是否对此有任何要求.我可以想到至少一种不需要完整类型的实现.)

This is because declaring the class member does not require Incomplete to be complete, but invoking the std::map destructor does, because it necessarily needs to invoke the Incomplete destructor to destroy the map contents. (Invoking the default std::map constructor could require the type to be complete, depending on the implementation. I'm not sure if the spec puts any requirements on this. I can think of at least one implementation that would not require complete types.)

如果你依赖编译器为你生成隐式ctors/dtors,那意味着当遇到类定义时类型必须是完整的,因为那时编译器将隐式生成ctors和dtors.就好像您在类定义之后立即编写了 inline Test::Test() {} inline Test::~Test() {} .dtor 会隐式地销毁地图,这将通过对任何存储的值调用 ~Incomplete() 来销毁地图内容,如果没有 Incomplete 的定义,我们就无法做到这一点.在那里,整个事情都崩溃了,你会得到一个错误.

If you rely on the compiler to generate implicit ctors/dtors for you, that means that the type must be complete when the class definition is encountered, because that's when the compiler is going to implicitly generate the ctor and dtor. It's as though you wrote inline Test::Test() {} inline Test::~Test() {} immediately following the class definition. The dtor is implicitly going to destroy the map, which is going to destroy the map contents by calling ~Incomplete() on any stored values, which we can't do without a definition for Incomplete. And there, the whole thing falls apart and you get an error.

但是,如果您告诉编译器(通过 Test ctor/dtor 声明)稍后将实现它们,那么它不会生成它们,因此此时不会编译 std::map ctor/dtor 调用.

However, if you tell the compiler (by way of the Test ctor/dtor declarations) that you will be implementing them later, then it won't generate them, therefore no std::map ctor/dtor invocation gets compiled at that point.

然后你在自己定义ctor/dtor之前完成Incomplete类型,这样Incompletector/dtor调用就可以被成功编译.如果您删除 Incomplete 的定义,那么您将遇到相同的错误.

Then you complete the Incomplete type prior to defining the ctor/dtor yourself, so the Incomplete ctor/dtor invocations can be successfully compiled. If you remove the definition of Incomplete then you will run into the same error.

请注意,正如其他人所说,您可以通过在映射中存储指向不完整类型的指针/引用来回避这个问题.指向不完整类型的指针或引用实际上本身就是一个完整类型.但是,这可能并非在所有情况下都是可取的,因此在不了解有关如何使用地图的更多详细信息的情况下,我对推动该解决方案犹豫不决.

Note that, as others have said, you can side-step this issue by storing pointers/references to the incomplete type in the map instead. A pointer or reference to an incomplete type is actually itself a complete type. However, this may not be desirable in all cases so I'm hesitant to push that solution without knowing more details about how the map will be used.

这篇关于作为 std::map 成员的不完整类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆