Doing some C++ development after a good four years in Python, it appears I'm a little rusty.
I have three files in my very cut-down example (the actual code is much larger but this example still exhibits the problem). They are the code for the main file, and the code and header for a separate component that it will use:
// 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.
};
}
Now, when I compile that with g++ --std=c++11 -o xx xx.cpp xx_store.cpp
, I get two warnings, one for each of the code files, but both referring to the same place in the header file:
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 {
| ^~~~~~~
Now I know from past experience that anonymous namespaces are per translation unit so it's unwise to do that in a header file that may be included by multiple code files.
But I can't see how the type of the m_map
variable (which is XXEntries
) is actually in the anonymous namespace. It's clearly inside the namespace XX { ... }
area in the header file, as is the XXEntry
type it depends upon. In fact, the warning even states that it's within the XX::
part of the namespace.
Can anyone suggest why this warning may be happening? I know I can disable the warning but I'd rather not go down that path until I'm sure it's a false positive.
The environment is Ubuntu 20.04
running g++ 9.4.0
.
using XXEntry = struct {
is a weird thing to do,struct XXEntry {
should work better.struct
is unnamed and it means its type is unique in each translation unit.using
is a modern replacement fortypedef
, but in this case you need neither, because in C++ (unlike C),struct XXEntry { }
already creates a type.typedef struct { int x; } XXEntry;
(useless as it is in C++) would have the same issue since that structure is similarly unnamed.