2011-05-09 5 views
14

재미있는 제목 죄송합니다.특성 클래스의 typedef에 익명 구조체

C++ 0x보다 먼저 함수 로컬 구조체 ("로컬 형식")를 템플릿 인수로 사용하는 경우 restrictions이 있습니다. 내 질문은 본질적으로 비슷한 제한이 익명 구조체에 적용되는 경우입니다. 구체적으로, 특성 클래스의 문맥에서 :

template <typename T> 
struct trait; 

template <> 
struct trait<int> { 
    typedef int type; 
}; 

template <typename T> 
struct trait<std::basic_string<T> > { 
    typedef struct { 
     T value; 
    } type; 
}; 

trait<std::string>::type foo; // Is this valid? 

template <typename T> 
void f() { } 

f<trait<std::string>::type> >(); // Is this? 

template <typename T> 
void g() { f<typename trait<T>::type>(); } 

g<std::string>(); // And this? 

유효하고 신뢰할 만합니까? 그것은 GCC와 LLVM의 최신 버전에서 컴파일되지만 이것이 VC++와 ICC에 의해 이해되는지 여부는 여전히 정확하지 않은지 여전히 불안합니다.

+0

질문 유형이 템플릿 인수로 사용되지 않았으므로이 유형이 로컬 유형에 대한 제한과 어떻게 관련이 있는지 잘 모르겠습니다. –

+0

@Luc 예제를 추가하겠습니다. 그러나 문제는 그 자체로 나타납니다. 위 내용이 유효합니까? 그렇다면 템플리트 인수로 유효합니까? –

+0

이제 익명 구조체의 인스턴스를 만들어 매개 변수로 사용하면 어떻게되는지 궁금합니다. (당신은'decltype'을 사용하여 그 타입을 얻을 수 있습니다) –

답변

3

typedef 해당 클래스에 대한 익명 클래스 및 typedef-name을 정의하는 선언문 인 typedef-name은 연결 목적으로 사용할 클래스의 이름입니다. 따라서 다른 클래스를 충족하는 경우 해당 클래스를 템플릿 매개 변수로 사용할 수 있습니다. typedef를 선언는 익명 클래스 (또는 열거)을 정의하는 경우

는 C++ 03 표준

의 7.1.3p5 참조 선언에 의해 선언 된 최초의 형식 정의 이름이 있다고 할 수 클래스 유형 (또는 열거 형 유형)은 연결 목적으로 (3.5) 클래스 유형 (또는 열거 형)을 나타내는 데 사용됩니다. [예 :

typedef struct { } *ps, S; // S is the class name for linkage purposes 

이는 C++ 0X FDIS에 7.1.3p9이다.

FWIW,이 코드는 MSVC2010 (모듈로 오타)에서 정상적으로 컴파일됩니다.

+0

분명히 알 수 있습니다 : 8.1.3p1 (Mark가 인용), typedef-name *을 가진 이름없는 클래스는 링키지를 가지고 있습니까? –

+2

그것은 함께 간다. 'typedef' 자체는 새로운 타입을 소개하지 않습니다. typedef 선언에 "inside"클래스 정의가 있습니다. 그런 다음 typedef는 새 유형의 이름을 제공합니다. 유형의 "the"이름은 아닙니다. 예를 들어, 클래스 정의 내에서 생성자 또는 소멸자를 정의하는 데 사용할 수는 없지만 "연결 목적으로"이름을 제공합니다. –

0

음, 즉 완전히 합법적

template <typename T> 
struct trait<std::basic_string<T> > { 
    struct type { 
     T value; 
    }; 
}; 

동일하다. 참고로

+0

감사합니다. 그러나 업데이트 된 질문도 참조하십시오. –

+0

사실, 나는 그것들을 동등하다고 생각 하겠지만 표준에 의해 동등한 것으로 정의 되었는가? –

+1

사실 그들은 유사하지만 동등하지 않습니다. 대답의 코드는 사용자 정의 유형에 대한 식별자 공간에서'traft :: type'을 정의하지만 질문의 코드는 그러한 식별자를 추가하지 않고 해당 식별자 공간의 별칭 * 외부 * 만 추가합니다. typedef는 여전히 (사용자가 정의한 식별자 공간에서) 이름이없는 유형을 참조하며 이는 해당 질문과 매우 관련이있을 수 있습니다. –

6

에 링크 된 질문에서 인용 14.3.1/2 :

로컬 유형, 이러한 유형의에서 를 혼합 익명의 유형이나 형식없이 연결과 유형 템플릿 형식 매개 변수 에 대한 템플릿 인수로 을 사용할 수 없습니다.

내 해석에 따르면 typedef struct은 이름이없는 유형의 별칭을 생성하므로 템플릿 유형 매개 변수로 사용할 수 없습니다. 더 나아가 C typedef struct {} Foo;의 추가 사항은 struct Foo {};과는 다소 다르게 취급됩니다. 두 양식이 동일하지 않다는 것을 전제로합니다 (비록 C++에서는 차이가 나타나지 않지만).

따라서 첫 번째 예제가 작동합니다 (템플릿 유형 매개 변수로 이름없는 유형을 사용하지 않기 때문에). 두 번째 및 세 번째 예제는 기술적으로 유효하지 않습니다 (템플릿 유형 매개 변수로 사용하기 때문에).

마침내 내가 물어야 만하는데, typedef 대신 구조체의 이름을 지정할 수없는 이유가 있습니까?

EDIT : 7.1.3/1에서 :

... 타입 정의 이름이 다른 유형의 대명사 따라서이다. 타입 정의-name은하지 길에 새로운 유형을 클래스 선언 (9.1) 또는 가하는 열거 선언 ...이 강하게 방식으로 typedef를 사용하여 유형에 적합 소개하지 않는 것을 의미한다

을 소개하지 템플리트 유형 매개 변수로 사용하십시오.

+0

"구조체의 이름을 지정할 수없는 이유가 있습니다."... 오히려 많은 실수 (!)가 중복 입력됩니다. 하지만 그 외에는 안돼. 따라서 안전과 표준 준수면에서 잘못 될 것입니다. –

+1

@Konrad : Erm은'typedef struct {} type;'struct type {};보다 중복 형식 지정이 아닙니다? 또는 나는 무엇인가 놓치고 있냐? – Xeo

+0

@Xeo 방금 나를 바보라고 공개 했나요? :-p 젠장, 때로는 나무에 나무가 보이지 않는다. –

4

곧 표준에서 언어에서 제한이 제거됩니다. 표준 말한다

14.3.1 [temp.arg.type]

에/1

타입은 타입 ID한다하는 템플릿 파라미터 템플릿 인수.

는 그리고 형식 정의는 유효한 유형-ID입니다.

14.3.1 [temp.arg.type (I 다른 대부분의 예를 트리밍 한)/2

template <class T> class X { }; 
template <class T> void f(T t) { } 
void f() { 
    typedef struct { } B; 
    B b; 
    X<B> x3; 
    f(b); 
} 

예를 보여준다 사실은 다음 단락은 예를 들어 있으므로 명명되지 않은 유형은 클래스 템플리트와 함수 템플리트 모두에서 클래스 템플리트 인수로 사용될 수 있습니다.

+0

아! 결국 권위있는 무언가. 우리는 함수의 익명 형식이 작동하면 구조체의 익명 형식도 단어이어야 함을 유추 할 수 있다고 생각할 수 있습니다. –

+0

14.3.1 [temp.arg.type]/1의 인용문은 충분하지 않습니다.모든 * type-id *가 유효한 템플리트 인수라고는하지 않습니다. 사실,'X '도 타입 ID를 사용하며 여전히 유효하지 않습니다. –

+0

@Johannes Schaub : 나는 그것을 검토했고'struct {}'은'type-id'라고 생각했다. (나는 생각하지 않았다.) 그리고 표준의 두 번째 인용문 (실제 예제) 사용되는 표준에 대한 예제를 제공하는데, 표준이 아니지만 이것이 허용됨을 나타내는 것으로 보인다. –

관련 문제