3

以下代码段无法使用 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++(如果是,为什么不)——编译它的解决方法很好,但不是这个问题的一部分。

4

4 回答 4

2

好吧,我也在codepad.org中尝试过它并且它可以编译,但我不确定它是否应该(不是精通 C++ 编译器功能)!

解决方法:也向前声明Bar,或者您必须Bar在 make 之前定义Foo。换句话说,这在 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;
}

更新: 我认为这可能已经是向微软报告的错误......这看起来非常接近:http ://connect.microsoft.com/VisualStudio/feedback/details/99218/invalid-error-c2888-when-a-类是在它被声明后定义的

微软引用的解决方法:

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). 
于 2011-11-09T19:18:28.353 回答
1

我认为代码格式正确。但要证明这一点,需要确保标准中没有任何与用法相矛盾的内容。

C++11 标准的一些相关引用:

3.3.2 p6:

首先在详细类型说明符中声明的类的声明点如下:

  • 用于类键标识符形式的详细类型说明符
    • 如果在命名空间范围内定义的函数的decl-specifier-seq参数声明子句中使用了详细类型说明符,则标识符在包含该声明的命名空间中声明为类名;否则,除了作为友元声明外,标识符在包含该声明的最小非类、非函数原型范围内声明。

3.4.4 p2:

如果详细类型说明符没有嵌套名称说明符,并且除非详细说明类型说明符出现在具有以下形式的声明中: class-key attribute-specifier-seq opt identifier 根据; 3.4查找标识符.1 但忽略已声明的任何非类型名称。... 如果详细类型说明符类键引入并且此查找未找到先前声明的类型名称,或者详细说明类型说明符 出现在具有以下形式的声明中: class-key 属性-specifier-seq 选择 标识符 ;详细类型说明符是一个引入类名的声明,如 3.3.2 中所述。

7.1.6 有一些语法定义,确定详细类型说明符在语法上可以是类型说明符。7.1 规定类型说明符在语法上可以是decl-specifier,它是用作函数参数声明(8.3.5) 中的类型的语法单元。

于 2011-11-09T19:55:57.490 回答
1

可能是编译器错误。

改变参数的顺序会改变编译结果。

namespace Test { 
void Foo (class Bar& b, class Baz& c) - will compile.
}
于 2011-11-09T19:34:34.547 回答
-2

构造class Bar是错误的。你是一个没有使用过的 C 程序员typedef struct { /* members */ } Foo吗?

Anywho,您需要在测试中同时定义 Bar 和 Baz:

namespace Test {
    class Bar;
    class Baz;
};

并在声明函数参数时删除classstructunion和关键字。enum

通过该修改,它可以在 g++4.6 中干净地编译。

于 2011-11-09T19:16:01.583 回答