2014-11-12 11 views
3

일부 라이브러리 코드를 작성 중이므로 가능한 경우 사용자가 정적 바인딩을 이용할 수 있기를 바랍니다. 클래스를 컴파일 할 때 클래스를 인스턴스화 할 수 없으면 클래스의 동적 버전이 있어야 런타임에 인스턴스화 할 수 있습니다. 동적클래스의 정적/동적 바인딩 버전을 생성 할 수있는 템플릿이 있습니까?

template<bool dynamic, int value=0> struct A 
{ 
    static const int Value = value; 
}; 


template<> struct A<true> 
{ 
    int Value; 
    A(int value) : Value(value) {} 
}; 

이러한 정의는 라이브러리의 사용자가 정적을 인스턴스화 할 수 있으며 : 빠른 예를 들어

, 나는 구조 템플릿 A를 갖고 있다고

A<true> dynamicA = A<true>(5); 

A<false, 5> staticA; 

이의 문제 방법은 클래스의 정의를 두 번 써야한다는 것입니다. 두 버전을 직접 생성 할 수있는 템플릿을 구현하는 몇 가지 방법을 생각해 볼 수 있지만 많은 작업이 될 수 있습니다. 이 패턴/문제에 대한 이름

// It would be much harder to generate a static version of this class, 
// though it is possible with type lists. Also, the way I'm imagining it, 
// the resulting classes probably wouldn't be very easy to use. 
struct A 
{ 
    vector<int> Values; 
    A(vector<int> value) : Values(value) {} 
}; 

있습니까 : 특히 예를 들어, 매개 변수의 숫자를 다양한 사용하는 것이 클래스? 나에게 정의를 생성 할 수있는 템플릿을 가진 메타 프로그래밍 라이브러리가 있습니까? 수업의 정의를 두 번 쓰지 않아도되는 방법은 무엇입니까?

+1

내가이 상황에서 "정적 바인딩"로 무슨 뜻인지 이해가 잘 모르겠어요; 'constexpr auto pseudostatic = A (5);의 무엇이 잘못 되었습니까? – dyp

+0

특정 클래스가 런타임에 인스턴스화되었는지 여부를 어떻게 감지합니까? – wowofbob

+1

dyp의 해결책이 직접적으로 적용 가능하지 않더라도'constexpr'은 아마 문제를 피할 수있는 열쇠 일 것입니다. 'A'를 템플릿으로 만들지 않아도됩니다. – MSalters

답변

3

동적/정적 값 문제에 의존하지 않는 부분을 단일 위치로 가져 오는 간단한 메커니즘이 있습니다. 다른 클래스에 넣고 basic_A으로 전화를 걸어 정적/동적 값 컨테이너를 호출합니다. 질문에 표시됩니다 value_A. value_A 내부 basic_A

  1. 집계 : 전체 A 클래스를 형성 value_Abasic_A를 연결하는 방법에는 여러 가지가 있습니다. 따라서 basic_A의 모든 방법을 value_A으로 라우팅하고 두 특수화에 해당하는 한자를 value_A으로 제공해야합니다. 모든 라이너를 복제해야하기 때문에 이것은 별 도움이되지 않을 것입니다.

  2. 집계 value_Abasic_A. 템플릿을 에 전달하고 두 특수화에 대한 올바른 생성자를 제공하여 SFINAE를 통해 설정을 해제하거나 가능하게하는 경우에만 basic_A 템플릿을 만들어야합니다. 매우 아름답고 관리하기 쉬운 코드가 아닙니다. 대안은 value_A이라는 두 가지 특수화에 대한 공통 기본 클래스 (인터페이스)를 만들고 해당 인터페이스에 unique_ptr을 사용하고 basic_A에 준비된 코드 value_Abasic_A의 생성자로 전달합니다. 가상 함수 호출과 poitner를 사용합니다 값에 액세스 할 때마다 간접 지정하십시오. Yuck, 특히 A은 작고 빠른 경량 클래스를 의미합니다.

  3. 계승 basic_Avalue_A. 템플릿 매개 변수의 생성자 및 전달과 관련하여 2.에서와 같은 문제가 적용됩니다.

  4. 상속 value_Abasic_A. 건설 문제는 사라지지만, 이제 basic_Avalue_A의 값에 쉽게 액세스 할 수 없습니다.한 가지 해결책은 의 basic_Avalue_A의 두 가지 특수화가 구현되어야하는 순수 가상 함수를 갖는 것입니다. 이것은 작은 가벼운 클래스에는 바람직하지 않을 수도있는 가상 함수 디스패치의 비용을 가지지 만, basic_A은 템플릿이 아니며 .cpp 파일에서 그 구현을 숨길 수 있기 때문에 캡슐화를 가능하게합니다. 다른 접근법은 basic_A을 다시 템플릿으로 만드는 CRTP를 통해 컴파일 타임 다형성을 사용하는 것입니다. 가상 함수getValue() :

    //basic_a.hpp 
    
    struct basic_A { 
        int foo() const; 
        virtual int getValue() const = 0; 
    }; 
    
    //basic_A.cpp 
    int basic_A::foo() const { return 10 * getValue(); } 
    

    4B :getValue() 비아 CRTP

여기서 4 :

(4a)의 두 가지 방식에 대한 두 가지 예

template <class Value_t> struct basic_A { int foo() const { return 10 * value_(); } private: int value_() const { return static_cast<Value_t const&>(*this).getValue(); } }; 

템플릿 A 일명. 4b에 대한 A_value이 뒤 따른다. 도 4a를 들어 그것은 일반 클래스이기 때문에 같은 alsmost, 단지 basic_A에서 템플릿 인수 및 브래킷을 잃을 수 있습니다 :

template <bool dyn, int value = 0> 
struct A; 

template <> 
struct A<true, 0> : basic_A<A<true, 0>> 
{ 
    int val; 
    int getValue() const { return val; } 
}; 

template <int value> 
struct A<false, value> : basic_A<A<false,value>> 
{ 
    int geValue() { return value; } 
}; 
+0

'basic_A'를 기본 클래스로 사용하여 가상 함수 호출없이 값에 액세스하는 CRTP 템플릿이 될 수도 있습니다. – aschepler

+0

@aschepler 정확히 내 마지막 예제에서 보여줍니다. 나는 코드를 보여주기 전에 두 가지 가능성을 강조하기 위해 약간의 답을 재구성 할 것이다. –