2011-11-09 5 views
3

다음 코드는 비주얼 스튜디오 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에
    • 사용된다면 그 않거나 계산 지정자-SEQ 또는 변수 선언 절 공간 범위에 정의 함수식별자가 이 선언을 포함하는 공간에 클래스 이름 선언되고 그렇지 않으면 친구 선언을 제외하고 식별자은 선언이 포함 된 가장 작은 비 클래스, 기능 외 프로토 타입 범위 인 에 선언됩니다.

3.4.4 P2 :

만약 정교 형 지정자가 나타납니다 않는중첩 된 이름 지정이 없으며, 형 지정자는 정교 다음 형식의 선언 : 클래스 키 속성 지정자 - seq 선택 식별자; 식별자은 l입니다. 3.4.1에 따라 작성되었지만 선언 된 비 유형 이름은 무시합니다. ... 는 형 지정자 정교클래스 키에 의해 도입이 조회는 이전에 선언 형 이름를 찾지 못하거나 이 형 지정자를 정교 경우 가 나타나는 경우 형태와 선언 : 급 키 속성 지정자-SEQ 옵트 식별자; 정교 형 지정자 3.3.2에 설명 된 클래스 이름 소개하는 선언이다.

7.1.6

이 정교 형 지정자 것을을 구문 형식 지정자 수 있습니다 수립 일부 구문 정의를 가지고있다. 7.1은 형식 지정자 이 구문 상명시 지정자 이 될 수 있음을 확인합니다. 매개 변수 선언 (8.3.5)의 형식으로 사용되는 구문 단위입니다.

-2

class Bar 구성에 오류가 있습니다. 혹시라도 C 프로그래머가 typedef struct { /* members */ } Foo을 사용하지 않았습니까?

됐건, 당신은 테스트 내부에 바 바즈을 모두 정의해야합니다

namespace Test { 
    class Bar; 
    class Baz; 
}; 

그리고 함수 매개 변수를 선언 할 때 class, struct, unionenum 키워드를 제거합니다.

해당 수정 사항은 g ++ 4.6에서 정상적으로 컴파일됩니다.

+1

OP 질문에 GCC가 그것을 컴파일했지만, MSVC는 대답하지 않았습니다. –

+0

'class bar'를 타입으로 사용하는 것이 가끔 허용됩니다. "때로는"복잡하기 때문에 그것을 피하는 것이 좋습니다. – aschepler

+0

GCC로 컴파일됩니다. _ 지금은 (GCC 4.5.1 및 GCC4.6.1)이므로 도움이되지 않습니다. – Anteru

2

글쎄, 나는 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; 
} 

가 업데이트

:이 이미 Microsoft에보고 된 버그 수 있다고 생각 ...이 아주 가까이 보인다 : 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). 
+2

'class Bar' *는 앞으로 선언되어야합니다. 나는 이것이 그 질문의 핵심이라고 생각한다. –

+0

네, Kerrek이 옳습니다. 나는 앞으로 선언한다고하더라도 그것이 작동한다는 것을 알고 있지만 이것은 잘 작동 할 것이다. Bar가 예를 들어 템플릿 메소드를 가지고 있지 않다면 작동 할 것입니다 ... – Anteru

+1

Anteru, MSVC의 버그 인 것 같습니다. Microsoft는 그것을 고치지 않을 것입니다 : http://connect.microsoft.com/VisualStudio/feedback/details/99218/invalid-error-c2888- class-is-defined-after-it-is-declared가 정의 된 경우 – Kiril

1

아마도 컴파일러 버그 일 수 있습니다.

매개 변수 순서를 변경하면 컴파일 결과가 변경됩니다.

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