2011-12-10 3 views
5

나는이 일하기 위해 할 수있는 일 : 아무튼있는자체 참조 템플릿

unknown type name 'Test' 

그것은 지금 자체 참조 템플릿 : 그것은 나에게 컴파일러 오류를 제공

template<class C, class V, Test V::*> 
class Test { 
}; 

을 가능한 것처럼 보입니다. 작동하게하려면 무엇을 할 수 있습니까?

편집 :

다음은 내가 필요한 것입니다. 최소한의 코딩 노력으로 양방향 (부모 - 자식 생각) 관계 스키마를 구현하고 싶습니다.

template <class O, class T, Reference<T, O, Reference O::*> T::* opposite> 
class Reference 
{ 
    T **data; 
    int count; 
public: 
    Reference(): data(new T*[N]), count(0) {} 
    ~Reference() {delete[] data;} 
    Reference &add(T *t) { 
     handleOtherSide(); 
     return link(t); 
    } 
    // a lot of stuff to implement this 
}; 

이것이 컬렉션 클래스입니다. 여기가 사용되는 방법은 다음과 같습니다

class Partner 
{ 
public: 
    Reference<Partner, Address, &Address::partner> addresses; 
}; 

class Address 
{ 
public: 
    Reference<Address, Partner, &Partner::addresses> partner; 
}; 

내 목표는 참조 파트너 및 주소 (현재 I가 제공하는 같은 클래스에 대한 생성자를 제공 할 필요가 없도록, 템플릿 인수로 제공 할 작동하는 데 필요한 모든 것을 가지고있다 생성자 arg로 반대 멤버 포인터하지만 이것은 참가자 클래스에 대한 명시 적 생성자가 필요합니다. Reference 클래스에 대한 "owner"포인터를 전달하거나 계산해야합니다. 내가 self-referencing 템플릿 측면에 초점을 맞추기 때문에이 문제를 여기에 남겼다.

이것을 생각하는 가장 쉬운 방법은 boost :: bimap입니다. 그러나 bimap의 문제점은 내가 묶는 bimap이 아니라 왼쪽과 오른쪽 부분을 원한다는 것입니다. bimap은 특정 관계의 모든 연관을 관리하는 하나의 bimap으로 이어지기 때문에 가능하지도 않습니다. 그것은 아마도 그것의 작업을 느리게하는 많은 수의 객체를 보유 할 것입니다.

+2

이것은 무엇입니까? 자체 참조보다이 방법을 구현하는 것이 훨씬 간단합니다. – Jon

+5

666 명의 평판 카운트에서 OP를 얻으려면이 질문을 업 보류해야했습니다. –

+2

내가 재귀 템플릿을 사용하여 달성하고자하는 목표는 무엇입니까? – dasblinkenlight

답변

1

문제는 무엇인지 내가 달성하고자하는 (읽기 : 회원 당 코드 한 줄을) 적어도 템플릿과 코드의 양 내가 목표로하고 클래스와 C++에서 수 없습니다. 이것은 순방향 선언과 완전히 정의 된 타입을 필요로하는 컴파일러로 시작합니다. 이는 순환 값 의존성의 경우 값이없는 멤버와 템플릿 인자를 불가능하게 만듭니다. 그런 다음 해당 멤버의 클래스가 아직 완전히 정의되지 않은 경우 멤버 포인터를 템플릿 arg로 가질 수 없습니다. 이 모든 근본적인 원인은 컴파일러가 작동하는 방식입니다. 단일 단계입니다. 그리고 제가 할 수있는 일은 없습니다.

해결 방법은 템플릿을 피하기 위해 참조 멤버 또는 OO 스타일 기본 클래스 또는 boost :: any 스타일 컨테이너를 사용하는 것입니다. 후자 2의 경우 가치가있는 회원을 가질 수 있습니다.

2

이 같은 것을 찾고 계십니까? 그것은하지 자체 참조 템플릿,하지만 당신은

template< typename PType, typename PDerived > 
class TBase 
{ 
    //do stuff with TDerived 
public: 
    bool foo(void) 
    { 
    return (static_cast< PDerived* > (this)->bar()); 
    } 
}; 

template< typename PType > 
class TDerived : public TBase< PType, TDerived<PType> > 
{ 
    friend class TBase< PType, TDerived<PType> > ; 
    //do stuff 
protected: 
    bool bar(void) 
    { 
    return (true); 
    } 
}; 

편집 도출 방법 등 : 호출 할 수있는 기본 클래스 및 기본 클래스에 대한 템플릿 형식으로 파생 클래스를 지정할 수 있습니다 최종 무엇을 다시 한 번 잘 모르겠어요를 골. 여기 내가 원하는 것, 또는 적어도 디자인을 구현하는 데 사용할 수있는 방법에 대한 힌트를 얻을 수있는 솔루션이 있습니다. 내가 요구하는 유일한 요구 사항은 TAddressTPartner이 모두 같은 이름을 가진 함수라는 것입니다. 그것이 당신이 필요로하는 것이 있는지보십시오. 원칙적으로 도우미 클래스를 만들고 CRTP를 사용하여 포인터를 통해 멤버 함수에 액세스 할 수 있지만 실제로 필요하지는 않습니다.

template< typename PType1, typename PType2 > 
class TReference 
{ 
public: 
    int mFlag; 

    TReference() : 
    mFlag(0) 
    { 
    } 
    TReference(int fFlag) : 
    mFlag(fFlag) 
    { 
    std::cout << "Creating reference " << PType1::sName << " -> " << PType2::sName << "." << std::endl; 
    } 
    TReference< PType2, PType1 > AccessOpposite(void) 
    { 
    PType2 lTmp; 
    lTmp.Opposite(); 

    return TReference< PType2, PType1 > (-1); 
    } 
}; 

class TPartner; 

class TAddress 
{ 
public: 
    static const char* sName; 
    TReference< TAddress, TPartner > mRef; 

    void Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

class TPartner 
{ 
public: 
    static const char* sName; 
    TReference< TPartner, TAddress > mRef; 

    TReference< TAddress, TPartner > Opposite(void) 
    { 
    std::cout << sName << "::Opposite" << std::endl; 
    } 
}; 

const char* TAddress::sName = "TAddress"; 
const char* TPartner::sName = "TPartner"; 

int main(void) 
{ 
TAddress lAddress; 
TPartner lPartner; 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

lPartner.mRef = lAddress.mRef.AccessOpposite(); 

std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl; 

return (0); 
} 
+0

매우 재미 있고 재미 있습니다. member bar()를 기본 클래스 수준으로 선언하지 않는 것이 좋습니까? –

+0

예, 템플릿 함수가 인스턴스화되는 방식 때문에 문제가되지 않습니다. 'foo'는 코드에서 실제로 호출 될 때까지 인스턴스화되지 않고'TDerived'가 이미 정의되어 있습니다. 자세한 정보를 얻으려면 CRTP를 검색하십시오. – lapk

+0

며칠 동안 이것을보고 난 후에 이것이 내 문제를 어떻게 해결할 수 있는지 말해야 만한다. 어쩌면 당신은 내가 솔루션을 볼 수 있도록 좀 더 내 예제를 채택 할 수 있을까요? –