2012-11-21 2 views
1

기본 클래스가 주어지면 모든 파생 클래스 (예 : 생성)와 같은 일반 논리로 public static 메서드가 포함됩니다. 매개 변수 유형의 자식 클래스 템플릿은 기본 클래스의 정적 메서드에서 사용자 지정 정적 메서드에 액세스 할 수 있도록 자식 클래스의 형식과 함께 기본 클래스 템플릿에 전달됩니다. 이러한 유형의 조합에서 새로운 "유형"(일부 코드의 중복을 피하기 위해 기본 클래스에서 수행됨)이 typedefed됩니다. 그런 다음 파생 된 클래스의 공개 섹션에서 형식을 다시 정의했습니다 (비슷한). 다음과 같이 나는 헬퍼를 포함한 클래스에 이러한 유형의 정의를 사용합니다 : 나는 헬퍼 클래스의 정의를 얻으려고템플릿 클래스의 템플릿 매개 변수에서 가져온 typedef는 보이지 않습니다.

#include <iostream> 
#include <vector> 

#include <cmath> 
#include <cstdlib> 

template< class DERIVED > 
class HELPERS; 

template< class V, class DERIVED > 
struct BASE 
{ 

    typedef typename V::value_type F; 

    static 
    F some_common_operation() 
    { 
     return helpers.approximate_x(DERIVED::value()); // some common logic (HELPERS::approximate_x() here) depending on the value of DERIVED::value() 
    } 

    static 
    DERIVED create_biased(F const & x) 
    { 
     return DERIVED(F(0.5) * (x + some_common_operation())); 
    } 

protected : 

    BASE(F const & x_) 
     : x(x_) 
    { ; } 

    F x; 

private : 

    static 
    HELPERS<DERIVED> const helpers; 

}; 

template< class V, class DERIVED > 
HELPERS<DERIVED> const BASE< V, DERIVED >::helpers; 

template< class V > 
class DERIVED 
    : public BASE< V, DERIVED<V> > 
{ 

    typedef BASE< V, DERIVED<V> > B; 
    friend B; 

public : 

    typedef typename B::F F; 

    DERIVED(F const & x_) 
     : B(x_) 
    { ; } 

    F shape(F const & y) const 
    { 
     return y * x; 
    } 

private : 

    static constexpr 
    F value() 
    { 
     return F(2.0L); // custom data 
    } 

    using B::x; 

}; 

// template<class> class DERIVED1;... 

template< class D > 
struct HELPERS // set of helpers, that operates on classes derived from BASE 
{ 

    typedef typename D::F F; // error: no type named <F> in <class DERIVED<std::vector<double> >> 

    F approximate_x(F const & x) const 
    { 
     using std::sqrt; 
     return sqrt(x); 
    } 

}; 

int main() 
{ 
    DERIVED< std::vector<double> > d(2.0L); 
    return EXIT_SUCCESS; 
} 

,하지만 난 g ++ -std = GNU ++ (오류가 11 a.cpp).

a.cpp: In instantiation of «struct HELPERS<DERIVED<std::vector<double> > >»: a.cpp:44:26: required from «struct BASE<std::vector<double>, DERIVED<std::vector<double> > >» a.cpp:47:7: required from «class DERIVED<std::vector<double> >» a.cpp:97:39: required from here a.cpp:85:27: error: no type named «F» in «class DERIVED<std::vector<double> >»

잘못 무엇입니까? Typedef와 모든 "조상"은 클래스 체인에서 액세스 할 수 있습니다 (공개 섹션에 배치).

답변

1

이것은 닭고기 달걀 문제입니다.

BASE을 정의 할 때 DERIVED이 아직 완전히 정의되지 않았기 때문에 (컴파일러가 먼저 기본 클래스를 해결해야하기 때문에) 문제가 발생했습니다. 따라서 DERIVED의 typedef는 HELPER에 액세스 할 수 없습니다. 당신은뿐만 아니라 작동하지 않는 경우 다음을 확인 할 수 있는지 확인하려면 다음

template< class V, class DERIVED > 
struct BASE 
{ 
    typedef typename V::value_type F; 
    typedef typename DERIVED::F G; // <-- error here 
    ... 
} 

는 당신이 시도 할 수있는 것은 DERIVEDHELPER의 사용을 이동하거나 HELPER에 대한 매개 변수로 V를 사용합니다.

+0

마지막으로'HELPER'의 매개 변수로'V'를 사용합니다. 그러나이 패턴은 템플릿 매개 변수의 수를 늘려 버리기 때문에 추한 것입니다. 필자는 HELPER를 매개 변수로 전달하지 않았습니다. 이는 파생 된 모든 클래스에 초점을 맞춰야하기 때문입니다. 매번 이것은 코드를 날려 버릴 것이다. – Orient

+0

Base는 이미'V'를 매개 변수로 취합니다. 왜 더 많은 매개 변수가 필요한지 잘 모르겠다면, 그냥'HELPER'로 바꿀 수 있었을까요? –

관련 문제