命名空间范围内的外部 - gcc vs clang vs msvc
extern in namespace scope - gcc vs clang vs msvc
我用最新的 gcc
、clang
和 MSVC
测试了下面看似奇怪的代码示例; clang 和 gcc 都给出 link 错误,但是 MSVC 编译和 links 没有任何问题。哪一个是正确的?
// foo.h
#pragma once
namespace A
{
class foo
{
public:
foo();
void print();
};
}
// foo.cpp
#include <iostream>
#include "foo.h"
int* p = nullptr;
using namespace A;
foo::foo()
{
p = new int(5);
}
void foo::print()
{
extern int* p;
std::cout << *p;
}
#include "foo.h"
int main()
{
A::foo f;
f.print();
}
gcc 和 clang:
foo.cpp:(.text+0x35): undefined reference to 'A::p'
GCC 和 Clang 都符合标准。示例和解释在标准中给出 [basic.namespace]/4:
The enclosing namespaces of a declaration are those namespaces in which the declaration lexically appears, except for a redeclaration of a namespace member outside its original namespace (e.g., a definition as specified in [namespace.memdef]). Such a redeclaration has the same enclosing namespaces as the original declaration.
[ Example:
namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
}
— end example]
我用最新的 gcc
、clang
和 MSVC
测试了下面看似奇怪的代码示例; clang 和 gcc 都给出 link 错误,但是 MSVC 编译和 links 没有任何问题。哪一个是正确的?
// foo.h
#pragma once
namespace A
{
class foo
{
public:
foo();
void print();
};
}
// foo.cpp
#include <iostream>
#include "foo.h"
int* p = nullptr;
using namespace A;
foo::foo()
{
p = new int(5);
}
void foo::print()
{
extern int* p;
std::cout << *p;
}
#include "foo.h"
int main()
{
A::foo f;
f.print();
}
gcc 和 clang:
foo.cpp:(.text+0x35): undefined reference to 'A::p'
GCC 和 Clang 都符合标准。示例和解释在标准中给出 [basic.namespace]/4:
The enclosing namespaces of a declaration are those namespaces in which the declaration lexically appears, except for a redeclaration of a namespace member outside its original namespace (e.g., a definition as specified in [namespace.memdef]). Such a redeclaration has the same enclosing namespaces as the original declaration. [ Example:
namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
}
— end example]