2013-02-03 1 views
3

나는 템플릿을 통해 정적 다형성을 사용하는 C++ 라이브러리에서 작업 중이다. 이 방법은 대상이 작은 스택이있는 임베디드 시스템이기 때문에 스택 용도로 저장하는 데는 구성원 함수 인 inline이 유용 할 때가 많기 때문에이 방법으로 설계되었습니다.GCC의 typeof() 확장을 멤버 액세스로 결합

정적 다형성에 대한 템플릿의 사용은 이벤트 이미 터의 유형의 이름 (대부분의 경우 장치 드라이버가) 종종 불쾌하게 긴 것을 의미

: 당신이 볼 수 있듯이

class DeviceThatUsesSPI<class SPI_BUS_TYPE> { 

    public: 
    class DeviceEvent : public Event<DeviceThatUsesSPI> {}; 

    // and the rest of the device driver implementation, including 
    // the code that emits that event. 

} 

SomeSpecificGpioBus gpio_bus(); 
SoftwareSpiBus<typeof(gpio_bus)> spi_bus(&gpio_bus); 
DeviceThatUsesSPI<typeof(spi_bus)> device(&spi_bus); 

, 우리는 GCC typeof 사용 확장 연산자를 사용하여 완전 불쾌한 유형 이름 DeviceThatUsesSPI<SoftwareSpiBus<SomeSpecificGpioBus>>을 반복 작성하는 것을 피하십시오. 이것은 오늘날까지 시도한 모든 곳의 매력처럼 작동했습니다. 이벤트를 나타내는 중첩 클래스에 액세스하려고 시도했습니다. 나의 현재의 예에서이 템플릿 특수화 구현 컴파일 타임 이벤트 핸들러 바인딩 :

typeof(device)::ExampleEvent event; 
:

template<> 
inline void event_handler<typeof(device)::ExampleEvent>(typeof(device) *emitter) { 
    // event handler implementation... 
} 

을하지만, 나는 또한 변수 선언의 훨씬 더 최소한의 예에서 이것을 시도했습니다

두 경우 모두 G ++은 구문 오류로 표현식을 구문 분석하지 못합니다. 이것은 표준 C++ 문법에서 식별자가 아닌 다른 것을 따르는 상황이없고 구문 분석기가 콜론을 만나면 유형을 첫 번째 부분을 역 추적하고 처리 할 수없는 상황이 아니기 때문이라고 가정합니다.

typeof 구조 어디서나 사용할 수있는 형식 정의 이름을 사용할 수 있습니다

그러나 the GCC manual about typeof이 연산자에 대한 다음과 같은 약속을합니다. 예를 들어, 선언, 캐스트 또는 sizeof 또는 typeof의 내부에서 사용할 수 있습니다. 나는 형식 정의 내 예에 typeof의 두 가지 용도를 교체 할 경우

은 G ++는 행복하다 :

typedef typeof(device) device_type; 

template<> 
inline void event_handler<device_type::ExampleEvent>(typeof(device) *emitter) { 
    // event handler implementation... 
} 

device_type::ExampleEvent event; 

그래서이 컴파일러는 내가 의미 쓴하지만 문법 것과 좋은 것을 내 의심을 발전한다 내가 그것을 표현하는 것을 허락하지 않는다. typedef 간접 사용을 사용하면 작업 코드를 얻지 만이 라이브러리의 사용자에게 편의를 위해 이벤트 처리기 선언을 자체 포함하는 방법을 찾는 것이 좋습니다. 구문 상 모호성을 제거하기 위해 typeof 연산자를 작성하여 이벤트 선언을 한 줄로 만들 수있는 방법이 있습니까?

+0

C++ 11에서는 컴파일러 확장 인'typeof' 대신'decltype'을 사용할 수 있습니다. – Nawaz

+0

내 솔루션이 작동하는지 알려주십시오. 그렇지 않으면 삭제할 것입니다. – Nawaz

답변

1

작은 메타 기능이 트릭을 수행 할 수 있다고 생각합니다.

: 다음으로 사용

template<typename T> 
struct event 
{ 
    typedef typename T::ExampleEvent type; 
}; 

:로

template<> 
inline void 
event_handler<self<typeof(device)>::type::ExampleEvent>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 

또는 당신은 ( 일반적이다) 메타 함수를 정의 할 수 있습니다

template<typename T> 
struct self 
{ 
    typedef T type; 
}; 

다음으로 사용

template<> 
inline void 
event_handler<event<typeof(device)>::type>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 
그런데

, C++ 11, 당신은 (컴파일러 확장입니다) decltype 대신 typeof 사용할 수 있습니다

template<> 
inline void 
event_handler<decltype(device)::ExampleEvent>(typeof(device) *emitter) 
{ 
    // event handler implementation... 
} 

희망을. :-)

+0

그게 효과가 있다는 뜻입니다. 큰! – Nawaz

+1

아하, 처음에는 당신의 코멘트를 알지 못했습니다. 이 트릭을 통해 이전 버전의 GCC에 shim을 추가 할 수 있었지만 GCC 4.7에서는 typeof 또는 decltype에 트릭이 필요하지 않음을 발견했습니다. 필자는 두 번째 대답에서 배운 것을 문서화했지만,이 파서 버그를 해결하는 방법에 대한 질문에 대한 답은 분명 더 직접적인 대답입니다. 감사! –

2

a bug report against GCC에 따르면 이는 알려진 문제이며 GCC 4.7에서 수정되었습니다. GCC 업그레이드는 장기적인 솔루션입니다.

버그 보고서는 이전 버전에 파서 해결하기 위해 간접으로 클래스 템플릿을 사용의 또 다른 해결 방법을 설명합니다,

class SameType<T> { 
    public: 
    typedef T R; 
} 
T<typeof(device)>::ExampleEvent event; 

는 모든 이벤트 유형에 일반화하기 때문이 형식 정의보다 더 좋네요을하지만, 그것은 여전히 ​​사용자에게 부자연 스럽습니다.

새 표준 decltype 연산자에 적용된 동일한 문제가 실제로 a C++11 specification change의 제목이었습니다.이 문제는 예상대로이 구문 분석을위한 형식 구문 분석 규칙을 명확히했습니다.