2011-11-09 31 views
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++或沒有(如果是這樣,爲什麼不是) - 解決方法讓它編譯好,但不是這個問題的一部分。

回答

1

我認爲代碼格式良好。但是證明某些方面需要確保標準中沒有與使用相矛盾的東西。

來自C++ 11標準的一些相關引用:

3.3。2點P6:

第一聲明的類的聲明的點闡述型說明符如下:

  • 用於闡述型說明符的表格級別密鑰標識符
    • 如果闡述類型說明符用於t他DECL說明符-SEQ參數聲明子句中的命名空間範圍內定義的 函數的,所述標識符被聲明爲在 包含聲明的命名空間的類名;否則,除了作爲朋友聲明,標識符在 最小的非包含聲明的非函數原型範圍中聲明。

3.4.4 P2:

如果闡述型說明符沒有嵌套名稱說明符,並且除非闡述型說明符出現在具有以下形式的聲明: class-key屬性 - 說明符 - seq opt標識符; 標識符是l根據3.4.1被忽略,但忽略已聲明的任何非類型名稱。 ......如果詳細擬訂類型說明符由 的類鍵引入此查找沒有找到先前聲明類型名,或者如果闡述型符 出現在與格式的聲明: 類-key屬性說明符-SEQ選擇標識符;闡述型說明符聲明,介紹如在3.3.2中描述的類名

7.1.6具有一定的語法定義是建立一個闡述型符可語法是類型說明符。 7.1確定類型說明符在語法上可以是decl說明符,它是在函數參數聲明(8.3.5)中用作類型的語法單元。

-2

class Bar構造是錯誤的。您是否有機會選擇不使用typedef struct { /* members */ } Foo的C程序員?

Anywho,您需要同時定義欄和巴茲內部測試:

namespace Test { 
    class Bar; 
    class Baz; 
}; 

,並聲明函數參數時刪除classstructunionenum關鍵字。

通過這種修改,它在g ++ 4.6中編譯乾淨。

+1

OP在問題中說GCC編譯它,MSVC沒有。 –

+0

有時允許使用'class Bar'作爲類型。避免這種情況通常是個好主意,因爲「有時」很複雜。 – aschepler

+0

它編譯GCC _as現在_(GCC 4.5.1和GCC4.6.1),所以這沒有幫助。 – Anteru

2

好吧,我在 codepad.org也試過,它編譯,但我不確定它應該(不是精通C++編譯器功能)!

解決方法:向前聲明Bar一樣好,甚至你必須定義Bar你做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; 
} 

更新: 我認爲,這可能已經報告給Microsoft的錯誤......這看起來八九不離十:http://connect.microsoft.com/VisualStudio/feedback/details/99218/invalid-error-c2888-when-a-class-is-defined-after-it-is-declared

解決方法引述微軟:

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). 
+2

'class Bar'*應該是前向聲明。我認爲這是問題的全部。 –

+0

是的,Kerrek是對的。我知道如果我更早地宣佈聲明,它就會起作用,但這也應該起作用。它會工作,如果酒吧沒有一個模板方法的例子... – Anteru

+1

Anteru,它看起來像它是MSVC中的錯誤,微軟是不會解決它:http://connect.microsoft.com/VisualStudio/feedback /信息/ 99218 /無效的錯誤-c2888-時-A-類的定義類後它,是申報 – Kiril

1

可能它是一個編譯器錯誤。

更改參數的順序將改變編譯結果。

namespace Test { 
void Foo (class Bar& b, class Baz& c) - will compile. 
}