开发者

C++: Linking extern variables from within a namespace

开发者 https://www.devze.com 2023-01-25 09:55 出处:网络
I can\'t seem to reference an externally-defined variable from within a namespace using extern.It works from the global scope, but as soon as a namespace is thrown in there,it fails to link.

I can't seem to reference an externally-defined variable from within a namespace using extern. It works from the global scope, but as soon as a namespace is thrown in there, it fails to link.

My constants file looks like:

StringConstants.cpp

#include "MyString.h"

MyString test1("string1");

MyString test2("string2");

The main program looks like this:

main.cpp

#include <stdio.h>
#include "MyString.h"

extern MyString test1;

namespace {
    extern MyString test2;
}

int main(void) {
    printf("%s\n", test1.Str());
    printf("%s\n", test2.Str());
}

I get similar errors in both GCC and Visual Studio:

gcc    main.o StringConstants.o   -o main
main.o:main.cpp:(.text+0x49): undefined reference to `(anonymous namespace)::test2'
collect2: ld returned 1 exit status

1>Linking...
1>main.obj : error LNK2001: unresolved external symbol "class MyString `anonymous namespace'::test2" (?test2@?A0x0df4aa01@@3VMyString@@A)
1>C:\p4\namespace_repro\namespace_repro2\Debug\namespace_repro2.exe : fatal error LNK1120: 1 unresolved externals

I tried qualifying the reference to test2 (extern MyString ::test2), but it just thinks that test2 is a static member of MyStr开发者_运维技巧ing. A named namespace doesn't behave differently than an anonymous one. For various reasons, we don't want to remove namespaces or put the externs outside of the namespaces.

Here's the other files, for completeness:

MyString.h

class MyString {
public:
   MyString(const char* str): mStr(str) {};
   const char* Str() const { return mStr; }
private:
   const char* mStr; 
};

Makefile

CC=gcc 
CFLAGS=-Wall

main: StringConstants.o main.o

The goals for this system are that the constants all be defined in one file, and that they be resolved at link time rather than being in a header. It seemed like the above code would work, but since it's rejected by two different linkers it seems my understanding of C++ is not good enough. Advice on how to get this to work, other than putting the externs outside of the namespaces?


What...

namespace { 
    extern MyString test2; 
} 

...does is say test2 should exist in an anonymous namespace, but it doesn't - it's in the global namespace. You've lied to your compiler, therefore it generates an object that won't link. You need the extern declaration to be made from the same namespace scope as the variable.

BUT, there should be a StringConstants.h, which main.cpp should include, such that the compilation unit knows about the strings without any further statements.


$7.3.1/2 - "Every name first declared in a namespace is a member of that namespace."

This means that the name 'test2' is part of the anonymous namespace and should be defined in that namespace if it is used.

It is not an issue with the anonymous namespace alone but for that matter any namespace.

0

精彩评论

暂无评论...
验证码 换一张
取 消