为什么编译器错误地陈述了命名空间?

Why is compiler mis-stating namespace?

提问人:paxdiablo 提问时间:9/21/2023 最后编辑:HolyBlackCatpaxdiablo 更新时间:9/21/2023 访问量:94

问:

在 Python 中工作了四年之后,我做了一些 C++ 开发,看来我有点生疏了。

在我非常精简的示例中,我有三个文件(实际代码要大得多,但这个示例仍然表现出问题)。它们是主文件的代码,以及它将使用的单独组件的代码和标头:

// xx.cpp:
#include "xx_store.h"
int main() {
    auto store = XX::XXStore();
    return 0;
}
// xx_store.cpp:
#include "xx_store.h"
namespace XX {
    XXStore::XXStore() : m_map(XXEntries()) { }
    XXStore::~XXStore() { }
}
// xx_store.h:
#include <map>
#include <string>
namespace XX {
    using XXEntry = struct {
        std::string m_value;
        bool m_found;
        uint32_t m_age_ms;
    };
    using XXEntries = std::map<std::string, XXEntry>;

    class XXStore {               // WHERE THE ERROR IS REPORTED.
    public:
        XXStore();
        ~XXStore();
    private:
        XXEntries m_map;          // THE APPARENT CAUSE.
    };
}

现在,当我使用 编译它时,我收到两个警告,每个代码文件一个,但都引用头文件中的同一位置:g++ --std=c++11 -o xx xx.cpp xx_store.cpp

xx_store.h:12:11: warning:
    ‘XX::XXStore’ has a field ‘XX::XXStore::m_map’ whose type uses
        the anonymous namespace [-Wsubobject-linkage]
        12 |     class XXStore {
           |           ^~~~~~~

现在我从过去的经验中知道,匿名命名空间是按翻译单元计算的,因此在可能包含多个代码文件的头文件中这样做是不明智的。

但是我看不出变量的类型(即)实际上在匿名命名空间是如何的。它显然位于头文件的区域内,它所依赖的类型也是如此。事实上,警告甚至指出它位于命名空间的一部分内。m_mapXXEntriesnamespace XX { ... }XXEntryXX::

谁能说出为什么会发生这个警告?我知道我可以禁用警告,但在我确定它是误报之前,我宁愿不走这条路。

环境正在运行。Ubuntu 20.04g++ 9.4.0

C++ C++11 GCC 命名空间 器警告

评论

1赞 HolyBlackCat 9/21/2023
using XXEntry = struct {是一件奇怪的事情,应该工作得更好。struct XXEntry {
0赞 paxdiablo 9/21/2023
@HolyBlackCat:嗯,这似乎确实已经修复了它,但我不确定为什么,因为别名使用应该是现代C++??无论如何,如果你给出一个答案,并至少提供一个适度可行的理由,我很乐意接受。
3赞 273K 9/21/2023
未命名,这意味着它的类型在每个翻译单元中都是唯一的。struct
0赞 wohlstad 9/21/2023
using是 的现代替代品,但在这种情况下,您两者都不需要,因为在 C++ 中(与 C 不同)已经创建了一个类型。typedefstruct XXEntry { }
2赞 paxdiablo 9/21/2023
@273K:啊,这是有道理的。这是我们要别名的匿名结构,每个翻译单元都不同。我想知道(在 C++ 中毫无用处)是否会有同样的问题,因为该结构同样未命名。typedef struct { int x; } XXEntry;

答: 暂无答案