1

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.

11
  • 1
    using XXEntry = struct { is a weird thing to do, struct XXEntry { should work better. Commented Sep 21, 2023 at 5:11
  • @HolyBlackCat: hmm, that does indeed appear to have fixed it but I'm not sure why, given the alias-with-using is supposed to be modern C++ ?? In any case, if you make that an answer and provide at least a moderately viable reason why, I'd be happy to accept.
    – paxdiablo
    Commented Sep 21, 2023 at 5:24
  • 3
    The struct is unnamed and it means its type is unique in each translation unit.
    – 3CxEZiVlQ
    Commented Sep 21, 2023 at 5:38
  • using is a modern replacement for typedef, but in this case you need neither, because in C++ (unlike C), struct XXEntry { } already creates a type.
    – wohlstad
    Commented Sep 21, 2023 at 5:54
  • 2
    @273K: Ah, that makes sense. It's the anonymous struct that we're aliasing, and it's different for each translation unit. I wonder whether typedef struct { int x; } XXEntry; (useless as it is in C++) would have the same issue since that structure is similarly unnamed.
    – paxdiablo
    Commented Sep 21, 2023 at 5:58

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.