嵌套命名空间与VS 2012的混淆

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌套命名空间与VS 2012的混淆相关的知识,希望对你有一定的参考价值。

我在VS 2012中遇到了一个非常简单的代码问题。我在centOS 7,Debian 8,9,Fedora 25,26,27,28和Ubuntu 14.04,16.04,18.04上测试了这个代码,最新的GCC和Clang编译器都在官方套餐,以及VS 2013,VS 2015,VS 2017.它的工作原理。

以下是有罪代码的最低版本:

file0.h

namespace B {
    enum bar {
        HELLO,
        WORLD
    };
}

file1.h

namespace A {
namespace B {
    // Some stuff
}
}

file2.h

#include "file0.h"

namespace A {
namespace C {

    template<::B::bar = ::B::HELLO> class foo {
        // Some stuff
    };    
}
}

main.cpp

#include <iostream>
#include "file0.h"
#include "file1.h"
#include "file2.h"

int main() {
    ::A::C::foo<> myFoo;
    // Some stuff
}

此代码导致VS 2012上的以下编译错误:

错误C2039:'bar':不是'A :: B'的成员

由于我们在file2.h中的命名空间::A::C(因此在命名空间::A中)并且要求命名空间::B,似乎VS 2012在::之前忽略B并首先在当前命名空间::A中搜索。由于它没有在bar中找到::A::B,它只会抛出错误而不是在更高级别的范围内搜索。

鉴于Stack Overflow上的following answer,VS 2012中的命名空间解析似乎存在错误。

我的问题是:

有没有办法解决这个问题而不改变名称空间的名称(对我来说,保持B在:: B和:: A :: B中非常重要)?就像使用其他语法来使用命名空间或使用别名命名空间一样?

注意:编辑了错误再现的代码(它实际上涉及第三个文件file0.h与我的原始帖子相比。我的错误)。

答案

我无法在视觉2013和2008上重现这个错误。它似乎是2010年和2012年的一个特定问题。

也许在命名空间声明之外尝试一个typedef:

namespace B {
    enum bar {
        HELLO,
        WORLD
    };
}
typedef ::B::bar my_type;
namespace A {
    namespace B {

        template<my_type= ::B::WORLD> class foo {
        };

    }
}

int main(int argc, char* argv[])
{
    A::B::foo<> myFoo;
}

以上是关于嵌套命名空间与VS 2012的混淆的主要内容,如果未能解决你的问题,请参考以下文章

嵌套片段过渡不正确

使用命名空间的区别(std:: vs ::std::)[重复]

在 .NET 中创建 C++ ATL COM 嵌套命名空间,如 System 命名空间

为啥我在vs2010下编写代码的时候代码下面会出现红色波浪线?

与嵌套选择混淆性能增益 * 不存在

嵌套命名空间路由到错误的控制器