2011-12-06 7 views
6

내가 해결하기 위해 노력하고이 퍼즐을 가지고 있고, 기본적으로 다음과 같은 예로 요약된다 :CRTP 입력 가시성

template <typename CT> 
struct A 
{ 
    typedef typename CT::VALUE_T FOO; // FOO is dependent on CT 
}; 

template <typename CT> 
struct B 
{ 
    typedef typename CT::BAR BAR; 

    BAR foo() {} 
}; 

template <typename DT> 
struct C : B<C<DT> > 
{ 
    typedef DT VALUE_T; 

    typedef typename A<C>::FOO BAR; 
}; 

int main() { 
    C<int> c; 
} 
내가 위의 설명을 시도 할 수 있습니다

(나는 시도했습니다 약 3 배 ! 등) 텍스트를 삭제하지만, 기본적으로 요구 사항은 다음과 같습니다

  1. CC (즉,) CRTP을 이용 B<C<>>
  2. 로 입력 B에서 상속해야합니다은 A을 인스턴스화 할 수있는 유일한 인터페이스입니다. A
  3. AFOO (FOO이 유형 CT에 따라 달라집니다 정의 할 수있는 유일한 사람입니다) C로 입력해야하며, 관계는 당신이 할 수있는 (발표가)

문제보다 더 복잡하다 위의 코드를 참조하십시오) BB 인 경우 내에서만 BAR 유형을 사용할 수 없으므로 B은 템플릿 인수 CT (C<int>) 유형을 볼 수 없습니다. 불행하게도 B 내에서 BAR 유형이 함수에 대한 인수로 사용되고 형식을 반환합니다 (즉, 함수 범위에만 국한되지 않아 결과적으로 typedef를 함수 범위로 이동할 수 없습니다).

이 방법이 있습니까? 위에 언급 된 관계를 깨뜨릴 수는 없습니다 (최후의 수단이 아니면). 아마도 C++ 11에서 auto을 사용하고 typedef를 B에 넣어야 할 필요가 없지만 현재로서는 아직 옵션이 아닙니다.

EDIT : @bitmasks의 의견에 이어 몇 가지 추가 정보가 있습니다.

    AB의 코드가 서로 다른 상황에서 꽤 많은 바이너리에 사용되는
  1. ,이 경우 유일한 독특한 상황이 CB에서 유래한다는 것입니다, 다른 경우에, C은에서 파생 된 무언가의 인스턴스를 소유 B.
  2. 템플릿 인수는 기존 용도 변경이 필요없는 값인 AB으로 기본값을 설정할 수있는 한 변경할 수 있습니다 (AB). 동일한 유형 세트는 기본값 인 템플리트 매개 변수 또는 다른 메커니즘으로 사용할 수 있어야합니다.

필자는 tight-coupling이 필요하기 때문에 여기서 템플릿을 사용하고 있으며 다른 상황에서 코드를 사용할 수있는 유연성이 필요했습니다.구성 요소의

대한 설명 :

  • A 최고의 컨테이너로 설명하고, FOO 정말 최고의으로 설명이 템플릿 매개 변수
  • B의 형식 정의에 의해 정의에 포함 된 내용 반복자이며, 일부 구성 요소에 의해 호출되는 함수 집합을 포함하는 기본 클래스 의 인스턴스는 C입니다. 이전의 경우에는 해당 구성 요소에 B에서 파생 된 내용에 대한 참조가 전달되었습니다 (이 경우 C에 의해 소유 됨).이 경우에는 C에 대한 참조를 제공합니다. 의미론 휴식의 변화 -

주요 합병증 용기 A 액세스 발생, BC 간의 이전 관계 C인스턴스 B이 있지만, 지금 C인스턴스B의가 있다는 클래스에 웨이 유형이 삽입됩니다.

+0

나는 오랫동안 당신의 문제에 대해 생각 해왔다. 나는이 앨리어스를 통해 우회를하고있는 이유에 대해 더 많은 정보를 제공해야하고, 당신의 예에 대한 변경이 용인 될 수 있다고 생각한다. 유형 등). – bitmask

+0

@bitmask, 시간 내 주셔서 감사합니다. 실제 코드가 부족하여 더 많은 정보를 추가했습니다.이 코드는 매우 민감하므로 게시 할 수 없습니다. 업데이트 상황을 설명하려고합니다. 문제의 핵심은 'C'와 'B'사이의 관계가 * a * 또는 *가 * a *인지 여부에 관계없이 유형을 사용할 수 있어야한다는 것입니다. – Nim

+0

@ 님 : 비트 마스크로 매우 혼란스럽고 친절하게 대답합니다. 왜 그런 상황에 처해 있는지 말할 수 있습니까? – Arunmu

답변

4

기본 템플릿 매개 변수로 순환 typedef 요구 사항을 해결할 수 있다고 생각합니다. (지금까지의 내가 질문을 이해) 의도를 (거의) 원래 코드의 모든 자유 잎으로 다음 작품 : 템플릿 유형이 끔찍한 도우미의

template <typename CT, typename CTVALUE_T = typename CT::VALUE_T> 
struct A 
{ 
    //typedef typename CT::VALUE_T FOO; // FOO is dependent on CT 
    typedef CTVALUE_T FOO; // FOO is dependent on CT 
}; 

template <typename CT, typename CTBAR = typename CT::BAR> 
struct B 
{ 
    //typedef typename CT::BAR BAR; 
    typedef CTBAR BAR; 

    BAR foo() {return 0;} 
}; 

template <typename DT> struct VALUE_T__from__DT { 
    typedef DT VALUE_T; 
}; 

template <typename DT, template <class T> class _C_ > struct BAR__from__DT { 
    typedef typename A<_C_<DT> , typename VALUE_T__from__DT<DT>::VALUE_T >::FOO BAR; 
}; 

template <typename DT> 
struct C : B<C<DT>, typename BAR__from__DT<DT, C >::BAR > 
{ 
    //typedef DT VALUE_T; 

    //typedef typename A<C>::FOO BAR; 
}; 

int main() { 
    C<int> c; 
    int x = c.foo(); 
    (void)x; 
    return 0; 
} 

이름, 아마 당신은 더 나은 찾을 수 있습니다 이름.

핵심 트릭은 문제가되는 typedef의 정의가 별도의 메타 컨테이너 (즉, 특성을위한 컨테이너)에 넣어져있어 거기에서 부두를 수행 할 수 있다는 것입니다.

필자는 불필요한 typedef를 주석 처리했지만 (거기에 남겨 두었기 때문에 내가하는 일을 파악할 수있는 기회가 더 많았습니다).

귀하의 필요에 맞습니까?

+0

좋은 답변입니다. +1 : – Arunmu

+1

@ArunMu : 고마워. 그것은 재미있는 (명백한 해결책은 없지만 분명히 사소한) 퍼즐에 완전히 저항 할 능력이 없다는 것입니다. – bitmask

+0

+1, 참으로 -이 모양이 좋아 보이네요, 지금 이걸 실제 코드로 어떻게 변환 할 수 있는지 알아야합니다. 'BAR__from__DT :: BAR'은'A :: FOO BAR'와 동일해야합니다. – Nim