首页 > 解决方案 > 命名空间范围内的外部 - gcc vs clang vs msvc

问题描述

我用最新gccclang, 和MSVC;测试了下面看似奇怪的代码示例 clang 和 gcc 都给出链接错误,但 MSVC 编译和链接没有任何问题。哪一个是正确的?

// 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'

标签: c++visual-c++namespaceslanguage-lawyerextern

解决方案


GCC 和 Clang 都符合标准。示例和解释在标准[basic.namespace]/4中给出:

声明的封闭命名空间是声明在词法上出现的命名空间,除了在其原始命名空间之外重新声明命名空间成员(例如,在 [namespace.memdef] 中指定的定义)。这样的重新声明具有与原始声明相同的封闭命名空间。[ 例子:

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
  }
}

——结束示例]


推荐阅读