C++ 在命名空间中正向定义类?
以下代码段无法使用Visual Studio 2010编译,但GCC喜欢它:C++ 在命名空间中正向定义类?,c++,visual-c++,compiler-errors,compiler-bug,C++,Visual C++,Compiler Errors,Compiler Bug,以下代码段无法使用Visual Studio 2010编译,但GCC喜欢它: namespace Test { class Baz; // Adding class Bar; here and removing the class below makes it work // with VC++, but it should work like this, shouldn't it? void Foo (Baz& b, class Bar& c)
namespace Test {
class Baz;
// Adding class Bar; here and removing the class below makes it work
// with VC++, but it should work like this, shouldn't it?
void Foo (Baz& b, class Bar& c);
}
namespace Test {
class Bar
{
// Making this method non-template works
template <typename T>
static void Lalala ()
{
}
};
}
int main ()
{
}
名称空间测试{
Baz类;
//在此处添加类栏;并删除下面的类,可以使其正常工作
//用VC++,但它应该是这样工作的,不是吗?
void Foo(Baz&b级、酒吧级和c级);
}
命名空间测试{
分类栏
{
//使此方法成为非模板有效
模板
静态空隙Lalala()
{
}
};
}
int main()
{
}
我是在做傻事还是这是一个有效的编译器错误?我得到的错误是:
错误C2888:'void Bar::Foo(void)':无法在命名空间“Test”中定义符号。
它按照GCC 4.5.1进行编译:
(编辑)我想清楚,我想知道这是否是C++的有效(如果是,为什么不)——解决它的方法是好的,但不是问题的一部分。
< P> >代码>类条< /代码>构造是错误的。你是一个没有使用typedef struct{/*members*/}Foo
的C程序员吗
总之,您需要定义Bar和Baz内部测试:
namespace Test {
class Bar;
class Baz;
};
并在声明函数参数时删除class
、struct
、union
和enum
关键字
使用了修改,它在G++ 4.6中简洁地编译。
,我也尝试过,它编译,但我不确定它应该(不精通C++编译器功能)!
解决方法:也向前声明Bar
,或者在创建Foo
之前必须定义Bar
。换句话说,这在MSVC中编译:
namespace Test
{
class Baz;
class Bar;// also forward-declare Bar
void Foo (Baz& b, class Bar& c);
}
namespace Test
{
class Bar
{
template <typename T>
static void Foo ()
{
}
};
}
int main(void)
{
return 0;
}
可能是编译器的错误 更改参数顺序将更改编译结果
namespace Test {
void Foo (class Bar& b, class Baz& c) - will compile.
}
我认为代码的格式很好。但要证明这一点,就必须确保标准中没有任何内容与用法相矛盾 C++11标准中的一些相关引用: 3.3.2 p6: 在详细的类型说明符中首先声明的类的声明点如下:
- 用于表单类键标识符的详细类型说明符
- 如果在decl说明符seq或 在命名空间作用域中定义的函数中,标识符被声明为 载有声明;否则,除非作为友元声明,否则将在 包含声明的最小非类、非函数原型范围
代码>
根据3.4.1查找标识符,但忽略已声明的任何非类型名称。。。如果详细的类型说明符是由
类键和此查找未找到以前声明的类型名,或者如果指定了详细的类型说明符
以以下形式出现在声明中:
类键属性说明符seq opt identifier代码>
详细的类型说明符是一个声明,它引入了类名,如3.3.2所述
7.1.6有一些语法定义,确定详细的类型说明符在语法上可以是类型说明符。7.1规定类型说明符在语法上可以是decl说明符,decl说明符是在函数参数声明(8.3.5)中用作类型的语法单位。OP在GCC编译它的问题中说,MSVC不允许。有时允许将类条
用作类型。避免这种情况通常是个好主意,因为“有时”是复杂的。它使用GCC编译,就像现在一样(GCC 4.5.1和GCC4.6.1),所以这没有帮助。@aschepler引用ISO 14882中定义此构造的部分。看起来参数中的fwd声明应该是不可编译的。不管是谁,看起来MSVC对作用域很挑剔,而函数参数作用域是不可以的-它必须在命名空间(扩展为类)作用域中。class Bar
应该是前向声明。我想这就是问题的关键所在。是的,克里是对的。我知道,如果我提前声明,它会起作用,但这也应该起作用。如果Bar没有模板方法,它就会工作。例如,Anteru,它看起来是MSVC中的一个bug,Microsoft不会修复它:
namespace Test {
void Foo (class Bar& b, class Baz& c) - will compile.
}