我在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.它的工作原理。
以下是有罪代码的最低版本:
namespace B {
enum bar {
HELLO,
WORLD
};
}
namespace A {
namespace B {
// Some stuff
}
}
#include "file0.h"
namespace A {
namespace C {
template<::B::bar = ::B::HELLO> class foo {
// Some stuff
};
}
}
#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;
}