2017-01-06 2 views
8

내가 구조체는 메타 프로그래밍 목적으로 다른 유형에 대한 유형 별칭을 포함시킬 :같은 이름을 사용하여 주변 범위의 유형에 멤버 유형 별칭을 선언해도됩니까?

struct Foo {}; 

struct WithNestedTypeAlias { 
    using Foo = Foo; 
}; 

는 그럼 난 템플릿에서 WithNestedTypeAlias::Foo 같은 물건을 할 수있는 등

내가 알고있는 것처럼

, 이러한 유형의 별칭은 유효 Foo 유형의 의미가 변경되지 않기 때문입니다. Clang은 이것을 행복하게 컴파일합니다.

그러나, GCC는 불평 : 나는 명시 적으로 struct Foo에서 Foo의 의미를 변경하지 않는거야 때문에

test-shadow-alias.cpp:4:20: error: declaration of ‘using Foo = struct Foo’ [-fpermissive] 
    using Foo = Foo; 
        ^
test-shadow-alias.cpp:1:8: error: changes meaning of ‘Foo’ from ‘struct Foo’ [-fpermissive] 
struct Foo {}; 
     ^

이 지금은 혼란 스러워요.

C++ 14의 올바른 동작은 무엇입니까? struct Foo의 이름을 바꾸면이 문제를 해결할 수 있지만 GCC의 오류가 올바른지 이해하고 싶습니다.

노트 :

+1

문을'Foo = :: Foo;를 사용하여 변경하면 수정되지만 그 이유는 설명 할 수 없습니다. –

+0

'using Foo = struct Foo;로 변경하면 수정됩니다. 이에 해당하는'typedef struct Foo Foo;'는 관용적 인 C 코드입니다. – Oktalist

답변

7

는 [basic.scope.class]이다 :

2)시 재 컨텍스트와 동일한 선언 참조한다 클래스 S에 이용되는 이름 N - 완료된 범위에서 평가 됨.이 규칙을 위반할 경우 진단은 필요하지 않음.

표준에 따르면 진단을 필요로하지 않으므로 GCC와 Clang이 모두 적합 할 수 있습니다 (GCC가 올바른 경우). 코드는 유효하지 않지만 컴파일러는 진단 할 필요가 없기 때문에 그것.

이 규칙의 목적은 클래스에서 사용되는 이름이 항상 동일한 것을 의미하며, 멤버를 다시 정렬해도 해당 멤버가 해석되는 방식이 변경되지 않습니다. 이 예에서

struct N { }; 

struct S { 
    int array[sizeof(N)]; 

    struct N { char buf[100]; }; 
}; 

이름 N 변화는 의미와 S::array의 크기를 변경 할 구성원을 재정렬. S::array이 정의 된 경우 N::N 유형을 나타내지 만 완료된 범위는 S이며 대신 S::N을 나타냅니다. 이것은 위에서 인용 한 규칙을 위반합니다.이름 훨씬 덜 위험한 방법으로 Foo 변경, 여전히 동일한 유형을 의미하기 때문에 당신의 예에서

그러나 엄격하게는 S::Foo의 선언에 ::Foo의 선언을 언급에서 변화를하지 말. 규칙은 선언을 언급하는 측면에서 표현되므로 GCC가 옳다고 생각합니다.

+0

흠, 그 규칙은 의미가 있습니다. 그러나 이것은 위의 설명에서 François Andrieux가 언급 한'using Foo = :: Foo' 트릭을 사용하지 말아야한다는 것을 암시하는 것처럼 보입니다. 그것이 현재 작동하는 동안, 그것은 여전히'Foo'의 새로운 선언이며 따라서 여러분의 인용 된 규칙을 위반합니다. 맞습니까? 그래서 그것은 유일한 해결책'struct AnotherFoo {};를 남겨 둘 것입니다. struct Nested {using Foo = AnotherFoo; }; Foo = AnotherFoo;를 사용하여 중첩 된'Foo' 선언을 이식 할 수 있습니다. – amon

+3

@amon : 원래 코드의 문제는 오른쪽에있는 'Foo'는 규정되지 않아 의미가 변경된다는 것입니다. 'using' 선언 이전에는 전역 Foo를 의미 할 것이고 나중에는 별칭을 의미했을 것입니다. 자격이되면 더 이상 문제가되지 않습니다. –

+2

@amon 또한 [Foo',':: Foo' 및 모든 것에 대한 귀하의 질문에 답변 할 [CWG 42] (http://wg21.link/cwg42) 참고 사항. – bogdan

관련 문제