2009-10-11 3 views
2

특정 인터페이스를 구현하는 유형을 허용하는 템플릿을 만들 수 있습니까? 예를 들어, 템플릿 사용자에게 말하고 싶습니다. Init() 및 Destroy() 메소드를 구현하는 동안에는 컨테이너에 아무 것도 저장할 수 있습니다.인터페이스를 시행하는 템플릿

감사합니다.

+1

이것은 http://stackoverflow.com/questions/1550370/c-polymorphic-class-template의 복제본입니다.하지만이 질문은 더 잘 쓰여지고 일반적입니다. =) – gnud

+0

이 질문을 이해하는 방법을 모르십니까? 컨테이너에 정확히 하나의 유형 (메소드를 지원함) 또는 다른 유형의 요소가 저장됩니까? – Dario

+0

컨테이너는 필수 인터페이스를 상속하고 구현 한 유형을 제공하는 모든 유형의 요소를 저장합니다. 예를 들어, 컨테이너는 요소가 삽입/제거 될 때 Element.Init() 및 Element.Destroy()를 호출 할 수 있습니다. – jackhab

답변

6

은 개념의 제한된 하위 집합 (의도적이지만 불행히도 단편화 된) C++ 0x 기능을 제공합니다. 필요한 인터페이스 용으로 concept check class을 만들어서 활용할 수 있습니다.

+0

C++ 0x 기능은 무엇입니까? 개념은 상처를주지 않았다. –

+0

피트 : 사실. 나는 "잠재적 인, 그러나 결국"C++ 0x 기능을 제거했다. –

+0

+1 불행히도 우리는 오랫동안 이것을 받아 들여야 할 것입니다 ... –

0

현재 표준에서는 불가능합니다. 나는 C++ 0x에서 '개념들'(?)이 표준이 될 수 있다고 믿는다.

+0

개념은 C++ 0x의 일부가 아닙니다. 더 이상 – Dario

+0

감사합니다. 잘 모르겠습니다. – Naveen

1

아니요, 불가능합니다.

템플릿은 유형으로 바뀌며 많은 차이가 없습니다.

모든 가능한 멤버가 상속해야하는 기본 클래스를 만들고 모든 템플릿을 그대로 두는 것이 좋습니다.

기본적으로 C++에서 지원되지 않는 existential types을 소개합니다.

0

음, 템플릿 인수에 Init()Destroy()을 호출하는 방법을 정의 할 수 있으며 어떻게 든이 메서드를 디버그 모드로 호출 할 수 있습니다.

또는 인터페이스를 정의하고 템플릿 구현에서이 인터페이스로 캐스팅 할 수 있습니다. 이것은 릴리스 모드에서도 사용할 수 없습니다.

2

첫 번째로 Init 및 Destroy가 필요하면 템플릿 코드가이를 사용한다는 뜻입니다. 즉, 유형이 해당 메소드를 가지고 있지 않으면 템플릿이 컴파일되지 않으므로 컴파일러에서 이미 존재 여부를 확인합니다. 당신이 그 (것)를 확인하려면

그러나 다음 방법 중 하나는, 어떤 컴파일시의 맥락에서 자신의 주소를 사용할 수 있습니다 예를 들어

는 꼬모으로 출력은
template <class T> 
class X 
{ 
private: 
    template <unsigned N> 
    struct Number {}; 
    Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy(); 
}; 

struct A 
{ 
    bool Init(); 
    void Destroy(); 
}; 

struct B {}; 

int main() 
{ 
    X<A>(); 
    X<B>(); 
} 

:

"ComeauTest.c", line 7: error: class "B" has no member "Init" 
      Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy(); 
          ^
      detected during instantiation of class "X<T> [with T=B]" at line 21 

"ComeauTest.c", line 7: error: class "B" has no member "Destroy" 
      Number<sizeof(&T::Init) + sizeof(&T::Destroy)> must_define_init_and_destroy(); 
              ^
      detected during instantiation of class "X<T> [with T=B]" at line 21 

그러나 필요한 방법 중 하나에 과부하가 걸리면이 문제가 발생하며 자연히이 방법이 적합한 프로토 타입인지 테스트하지 못합니다.

예 : bool Init (int, int). 정확한 서명을 확인하기 위해 static_cast를 사용할 수는 있지만 다시 말하면 유형에 대한 불필요한 제한이있을 수 있습니다. 예를 들어, 어떤 클래스에 bool Init (long, long)이 있다면 어떻게 될까요?

이러한 노력은 오류 메시지를보다 명확하게 만 드러내는 데 필요한 것 같습니다. 그러나, 나는 당신이 달리 개념 체크없이 얻을 수있는 메시지 ("여기에 사용될 때 T = X로 초기화하는 적합한 초기화 메소드가 없다")가 그렇게 나쁘다는 것을 매우 의심합니다.

0

예, 가능합니다.

그러나 매우 복잡합니다 (고급 템플릿 메타 프로그래밍) 전체 개념은 "대체 오류가 C++ 템플릿의 오류 (SFINAE)"품질을 기반으로 작성되었습니다.

은 본질적으로, 당신은 'template <typename T, void (T::*)()>' 같은 것을 사용하여 템플릿과 벡터에 <T, T::Init>를 사용하여 인스턴스화 할 수 있습니다. 대체가 존재하지 않으면 대체 오류가 발생합니다 (대신 SFINAE 원칙이 생성자를 대신 사용하기 때문에 여기에서 사용됩니다).

이것은 물론 간략한 설명입니다. 죄송합니다. 현재 더 좋은 서비스를 제공 할 수 없지만 this discussion을보고 싶을 수도 있습니다. has_member 및 is_call_possible을 검색하십시오.

도움이되기를 바랍니다.
오렌은

0

사실, 그 반대의 : 템플릿이 Init()Destroy()을 필요로하는 경우, 그것은 하지이 두 가지를 가지고 모든 유형을 인스턴스화하는 것은 불가능하다.

템플릿과 관련된 유일한 문제는 요구 사항이 암시 적이라는 것입니다 (즉 템플릿이 템플릿 내에서 필요한 지점에서 컴파일되지 않음). 명시 적이 아닙니다. 즉 컴파일러가 인스턴스화 시점). 개념은 그것을 고치려고했지만 얼마 전에 그들은 taken out of the next standard입니다.

관련 문제