我有一个带有MS Visual Studio 2015的大型C ++ 11项目,它在两个模块(=编译单元,cpp文件)中定义了两个具有相同名称但内容不同的结构。由于stucts仅在模块中定义和使用,而不是通过任何头文件导出以供共享使用,因此应该允许这样,实际上编译器和链接器都不会报告任何错误或警告。但是在运行时,我从包含结构的无序映射的构造函数中获取访问冲突。 Visual Studio 2017也会出现此问题,但不适用于gcc5.4。在我看来这是一个编译器错误,但我不是很确定。 下面是一些重现问题的最小化源代码,只需链接任何可执行文件,以便在main()之前启动时获取访问冲突。
module1.cpp:
#include <unordered_map>
struct AmbigousStruct {
int i1;
int i2;
int i3;
};
static const std::unordered_map<int, AmbigousStruct>
s_ambigousStructMap{
{ 0, { 0, 1, 2 } }
};
module2.cpp:
#include <unordered_map>
struct AmbigousStruct {
int i1;
int i2;
};
static const std::unordered_map<int, AmbigousStruct>
s_ambigousStructMap{
{ 0, { 0, 1 } }
};
问题似乎与在模板类中使用struct(在本例中为unordered_map)有关,因为它不会出现在struct的简单实例中,即module2.cpp:
static const AmbigousStruct s_ambigousStructInstance{ 0, 1 };
答案 0 :(得分:1)
您有两种具有外部链接的类类型,具有相同的名称,以不同的翻译单位定义。他们的成员不匹配,并且违反了One Definition Rule。您的程序格式错误,无需诊断。
您需要强制该结构定义上的内部链接。 C ++标准允许您使用匿名命名空间执行此操作。实际上,匿名命名空间使中的所有具有内部链接。因此,您不需要static
修饰符来处理其他事情:
namespace {
struct AmbigousStruct {
int i1;
int i2;
};
const std::unordered_map<int, AmbigousStruct>
s_ambigousStructMap {
{ 0, { 0, 1 } }
};
}
答案 1 :(得分:0)
这是一个链接器问题,而不是编译器错误。链接器将采用找到的第一个定义并忽略第二个定义。
要解决此问题,请使用未命名的命名空间,以用于仅在翻译单元中本地使用的任何内容:
namespace { // Everything contained is only visible in the current
// translation unit
struct AmbigousStruct {
int i1;
int i2;
int i3;
};
const std::unordered_map<int, AmbigousStruct> s_ambigousStructMap {
{ 0, { 0, 1, 2 } }
};
}
在另一个.cpp
文件中也是如此。