在命名空间中向前定义类
Forward defining class in namespace?
下面的代码片段无法在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 Bar
{
// Making this method non-template works
template <typename T>
static void Lalala ()
{
}
};
}
int main ()
{
}
我在这里做了一些愚蠢的事情还是这是一个有效的编译器错误?我得到的错误是:error C2888: 'void Bar::Foo(void)' : symbol cannot be defined within namespace 'Test'
使用GCC 4.5.1编译:http://ideone.com/7sImY
[编辑]只是为了清楚,我想知道如果这是有效的c++或不(如果是这样,为什么不)-变通方法得到它编译是很好的,但不是这个问题的一部分。
嗯,我在codepad.org上也试过了,它可以编译,但我不确定它应该(不是那么精通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;
}
更新:我想这可能已经是向微软报告的bug了……这看起来很接近:http://connect.microsoft.com/VisualStudio/feedback/details/99218/invalid-error-c2888-when-a-class-is-defined-after-it-is-declared
Microsoft引用的变通方法:
A stand-alone forward declaration consists of an elaborated type specifier followed by a semicolon.
insert the declaration
class C2888;
before the declaration of foo(C2888o, C2888).
我认为代码格式良好。但要证明这一点,就需要确保标准中没有任何与用法相矛盾的内容。
c++ 11标准中的一些相关引用:
3.3.2 p6:
首先在详细类型说明符中声明的类的声明点如下:
- 用于类键标识符形式的详细类型说明符
- 如果详细类型说明符在decl- specific -seq或参数声明子句中使用了,则
- 在命名空间作用域中定义的函数,标识符在命名空间中声明为类名包含声明;否则,除了作为友元声明外,标识符在包含声明的最小非类、非函数原型范围。
3.4.4 p2:
如果精心设计的类型说明符没有嵌套的名称说明符,并且除非精心设计的类型说明符以以下形式出现在声明中:class-key attribute-specifier-seq opt identifier
;
标识符根据3.4.1查找,但忽略已声明的任何非类型名称. ...如果精心设计的类型说明符是由类键和此查找没有找到先前声明的类型名称,或者如果详细类型说明符出现在声明中,格式为:class-key attribute-specifier-seq opt identifier;
详细类型说明符是一个声明,它引入了3.3.2中描述的类名。
7.1.6有一些语法定义,建立了详细类型说明符在语法上可以是类型说明符。7.1规定类型说明符在语法上可以是decl说明符,这是在函数参数声明(8.3.5)中用作类型的语法单位。
可能是编译器错误。
改变参数的顺序将改变编译结果。
namespace Test {
void Foo (class Bar& b, class Baz& c) - will compile.
}
class Bar
结构是错误的。你是一个没有使用typedef struct { /* members */ } Foo
的C程序员吗?
无论如何,您需要在test中定义Bar和Baz:
namespace Test {
class Bar;
class Baz;
};
并在声明函数参数时删除class
、struct
、union
、enum
关键字。
- 在命名空间中定义函数还是限定函数
- 使用命名空间时出现多个定义错误
- 如何对命名空间限定类型进行类型定义?
- C++未定义的命名空间
- 命名空间更改函数定义
- 使用命名空间在另一个".cpp"文件中定义
- 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见
- 在方法定义中显式指定命名空间
- 在 c++ 中定义命名空间中模板类的友元函数时出现问题
- 与自定义命名空间一起使用时实现 std::error_category、名称解析问题
- 为什么 ADL 优先于'std namespace'中的函数,但等于用户定义命名空间中的函数?
- G++显示关于未定义命名空间的错误
- 定义命名空间内类的构造函数
- 在自定义命名空间下包含一个标头
- 与自定义命名空间的链接失败未解析的外部符号
- 自定义命名空间的链接器错误
- 试图通过using-declaration定义命名空间成员
- 如何正确重载作为用户定义命名空间一部分的模板化类的插入运算符?
- 定义命名空间的变体和__visibility__的含义
- 重新定义命名空间的变量