2010-04-02 5 views
4

일부 기본 C++ 클래스를보다 쉽게 ​​래핑 할 수 있도록 일반 IEnumerable 구현을 만들고 싶습니다. 템플릿 매개 변수를 IEnumerable의 매개 변수로 사용하여 구현을 만들려고하면 오류가 발생합니다.System :: Collections :: Generic :: IEnumerable <T>의 템플릿 기반 하위 클래스를 만들 수없는 이유는 무엇입니까?

여기에 내가 그 해낸의 간단한 버전의 내 문제를 보여줍니다 표시된 줄에

ref class A {}; 

template<class B> 
ref class Test : public System::Collections::Generic::IEnumerable<B^> // error C3225... 
{}; 

void test() 
{ 
    Test<A> ^a = gcnew Test<A>(); 
} 

을,이 오류가 발생합니다 :

error C3225: generic type argument for 'T' cannot be 'B ^', it must be a value type or a handle to a reference type

나는 다른 상위 클래스를 사용하는 경우 문제가 보이지 않습니다.

template<class P> 
ref class Parent {}; 

ref class A {}; 

template<class B> 
ref class Test : public Parent<B^> // no problem here 
{}; 

void test() 
{ 
    Test<A> ^a = gcnew Test<A>(); 
} 

다른 템플릿을 추가하여 해결할 수 있습니다. para 미터를 구현 유형으로 바꾸십시오.

ref class A {}; 

template<class B, class Enumerable> 
ref class Test : public Enumerable 
{}; 

void test() 
{ 
    using namespace System::Collections::Generic; 
    Test<A, IEnumerable<A^>> ^a = gcnew Test<A, IEnumerable<A^>>(); 
} 

그러나 이것은 나에게 지저분 해 보입니다. 또한, 나는 여기서 무슨 일이 일어나고 있는지 이해하고 싶습니다 - 왜 첫번째 방법이 효과가 없습니까?

첫 번째 예에서

답변

3

, 귀하의 상속 라인은 읽을해야합니다

ref class Test : public System::Collections::Generic::IEnumerable<B> 

(템플릿에는 기준 마커)를

이 그런 다음 사용 라인을 읽어야합니다

Test<A^> ^a = gcnew Test<A^>(); 

참조 마커는 템플릿 자체가 아니라 템플릿의 인스턴스화 과정을 거칩니다.

여기에 컴파일 가능한, 샘플입니다 :

using namespace System; 
using namespace System::Collections::Generic; 

ref class A {}; 

template<class B> ref class Test : public System::Collections::Generic::IEnumerable<B> 
{ 
public: 
    B GetInstance() 
    { 
     return Activator::CreateInstance<B>(); 
    } 

    virtual System::Collections::IEnumerator^ GetEnumeratorObj() = 
     System::Collections::IEnumerable::GetEnumerator 
    { 
     return nullptr; 
    } 

    virtual System::Collections::Generic::IEnumerator<B>^ GetEnumerator() 
    { 
     return nullptr; 
    } 
}; 

void test() 
{ 
    Test<A^> ^a = gcnew Test<A^>(); 
} 

편집 : 이것은 내가 왜 설명해야 실현. IEnumerable 상속에 B ^를 지정할 수없는 이유는 IEnumerable이 제약 조건이있는 제네릭이고 B는 제약이없는 템플릿 매개 변수이기 때문입니다. 템플릿은 C++/CLI에서도 여전히 효과적으로 "구문 분석 된 텍스트"이므로 ref 객체를 제어 할 때도 훨씬 유연한 구문을 허용합니다. 그러나 제약 조건이있는 제네릭과 충돌 할 경우 규칙이 훨씬 엄격 해집니다.

+0

감사합니다. 초기 문제가 해결되었습니다. 질문의 일부를 나갔다. Test 클래스 안에 B의 새로운 인스턴스를 만들고 싶다. 당신의 솔루션으로, B가 핸들 타입이기 때문에 gcnew B()가 실패합니다. 그 주위에 방법이 있습니까? – fiirhok

+1

그래, 전혀 직관적이지는 않지만. 'Activator :: CreateInstance ()'을 사용하십시오. 위의 샘플을 업데이트하여 시연했습니다. –

관련 문제