2010-01-03 6 views
0

템플릿을 사용하면 C++에서 자동으로 같은 인터페이스로 여러 클래스를 만들 수 있지만 다른 데이터를 저장할 수 있습니다.C++은 다양한 필드 조합으로 클래스 변형을 생성합니다.

나는 datamembers의 하위 집합 만 저장하는 개체의 유사 콘텐츠를 자동으로 생성하는 유사한 (내가 존재하는지 여부는 모르겠다.) 이유를 찾고 있습니다.

의 난이

class FullClass 
{ 
public: 
    bool A; 
    int B; 
    float C; 
    double D; 
}; 

그때 내가 예를 들어 같은 그 필드의 모든 가능한 조합하고 싶은 있다고 가정 해 봅시다 :

class BDClass 
{ 
public: 
    int B; 
    double D; 
}; 

또는

class BCDClass 
{ 
public: 
    int B; 
    float C; 
    double D; 
}; 

과 내가 원하는을 정의 된 필드가 복사 될 수 있도록 모든 변형 클래스에서 FullClass로 형변환 할 수 있어야합니다. 차 누락 된 필드는 defaultvalues로 설정됩니다

FullClass foo; 
BDClass bar = BDClass(3, 5.0); 
foo = (FullClass) bar; 

컴파일러가 나를 위해 그 변화를 만들어 보자, 아니면 모든 가능한 조합 자신을 정의해야 할 어떤 메커니즘이 있습니까?

감사합니다.

편집 :

왜 내가 이것을 찾고 있습니까?

나는 전략 패턴을 따르는 소프트웨어 구조를 가지고 있습니다. 따라서, 나는 같은 인터페이스를 사용하여 (30 개 이상의) 다른 알고리즘을 가지고있다. 클라이언트는 현재 실행중인 정확한 알고리즘을 모른 채이 인터페이스를 사용할 수 있어야합니다. 클라이언트는 이러한 'FullClass'개체를 계산하여 인터페이스를 통과시킵니다. 그러나 각 알고리즘은이 개체에서 제공되는 필드의 하위 집합 만 사용하며 각 알고리즘은 다른 알고리즘을 사용합니다. 이 전략 패턴 구성은 고정되어 있으며 변경할 수 없습니다.

이제 생성 된 'FullClass'객체의 시퀀스를 '기록'하여 이러한 'FullClass'객체를 다시 계산하지 않고도이 구성 사용법의 전체 흐름을 반복 할 수 있습니다. 그러나 이것은 많은 데이터 (성능상의 이유로 메인 메모리에 보관하고 싶습니다)와 알고리즘의 대부분이 필드의 작은 하위 집합만을 사용하기 때문에 효과적으로 사용되는 필드를 저장하려고합니다.

+1

아니요. 이렇게하면 해결하려는 문제를 설명하는 것이 좋습니다. –

+0

속성을 공개하는 것은 나쁜 생각이라는 점에 유의하십시오. 그들을 비공개로 만들고 세터와 게터를 추가하십시오. –

+0

닐 : 설명을 위해 제 편집문을 읽으십시오 – genesys

답변

1

이 필요합니까 왜 내가 상상조차 할 수 없지만, 당신이 사용이나 mixin 시도 할 수 있습니다 :

class Dummy 
{ 
}; 

<template Base> 
class AClass : public Base 
{ 
    public: 
      bool A; 
}; 

<template Base> 
class BClass : public Base 
{ 
    public: 
      int B; 
}; 

... //(etc) 

BClass< AClass<Dummy>> abClass; 
abClass.B = 4; 
abClass.A = false; 

을 그리고 당신은 계속한다면 당신은 할 수있을 것입니다 :

DClass< CCLass< BClass< AClass<Dummy>>>> abcdClass; 
+0

깔끔하게 보입니다! 나는 그것을 시도 할 것이다! – genesys

+0

변수를 abClass에서 abcdClass로 변환 할 수 있습니까? – genesys

+0

나의 첫 번째 의도는 '아니오'라고 말하지만 실제로 검증 할 필요가 있다는 의미이기 때문에 실제로 검증해야합니다. abcdClass를 abClass에 할당 할 수 있어야한다고 가정 해 보겠습니다. –

0

먼저 당신이 할 수 각 데이터 유형에 대해 네 개의 클래스를 정의한 다음 유형 쌍에 대한 templae 클래스를 선언 한 다음 세 가지에 대해 선언하십시오 유형 조합, 그 다음에 4 가지. 그것보다 더 간단하게 할 수는 없습니다.

+0

변환 기준을 충족하지 못합니다. –

0

나는 당신이 개인 수준의 데이터 패턴을 사용하여 뭔가를 할 수 있다고 생각하고 끔찍한 memcopy 트릭 : 다음

class Full 
{ 
private: 
    struct fullData 
    { 
     a; 
     b; 
     c; 
     d; 
     e; 
     ... 
     z; 
    } * m_pData; 
public: 
    Stuff! 
} 

class Partial 
{ 
private: 
    struct partialData 
    { 
     a; 
     b; 
     c_filler; //This is an issue 
     d; 
    } 
public: 
    Different Stuff!; 
} 

, 당신은 복사 할 때, 단지 문자 그대로 나머지를 채우는 fullData에 partialData의 메모리를 복사 fullData와 0을

이것은 생성자를 사용할 필요가없는 데이터 유형에서만 작동하므로 (여기서는 안전성 검사가 필요하지 않습니다), 데이터를 채우기 위해 (위와 같이) 패딩을 넣어야한다는 것이 문제입니다 제대로 정렬.

하지만 복사 생성자가 memcopy가되고 나서 memfill이됩니다. (주, 나는 거의 확실 memcopy을 가지고 구문을 잘못 입력)

template<class T> 
Full(T& t) 
{ 
    m_pData = new fullData; 
    memcopy(/*to*/m_pData, /*from*/Partial->getData(), /*how much to copy*/ sizeof(T)); 
    memfill(/*tp*/m_pData, /*how much to copy*/ sizeof(fullData) - sizeof(T), /*with*/ 0); 
} 

가 특정 상황에 작동 할 수 있지만, 특히 안전하지 또는 꽤.

0

codegen에 필요한 전처리기를 작성한 것으로 생각하십니까?

+0

전 전처 리기에서 이것을 생성하기 위해 for-loop를 필요로한다고 생각합니다 - 루프를 수행하는 전처리 지시어가 있습니까? – genesys

+0

아니, 나는 코드 gen을하는 자신의 프로그램을 작성하는 것을 의미한다. 아마도 전처리 기라는 단어의 사용이 잘못되었을 수 있습니다. –

0

나는 개인적으로 정말 Boost.Fusion을 주셔서 감사합니다, 그것은 아주 쉽게 유형을 혼합 할 수 있기 때문에) 여기

, 나는 boost::fusion::map를 사용합니다.

데이터를 저장하는 데 사용되는 태그 유형 (컴파일 용도로만 사용되는 유형)과 실제 유형의 조합을 사용해야합니다.

의 우리의 태그를 정의 할 수 있습니다 : 그런 다음 태그 목록을 받아 같은 적절한 boost::fusion::map

GENERATE_MY_TYPE(TypeName, (a_tag)(b_tag)(c_tag)(d_tag)); 

// For information: (a_tag)(b_tag)(c_tag)(d_tag) is called a sequence in PP 

유형은한다 무언가를 생성 Boost.Preprocessor를 사용하여 매크로를 기록 할 수

class a_tag { typedef bool type; }; 
class b_tag { typedef int type; }; 
class c_tag { typedef float type; }; 
class d_tag { typedef double type; }; 

을 :

typedef boost::fusion::map< 
    std::pair<a_tag, a_tag::type>, 
    std::pair<b_tag, b_tag::type>, 
    std::pair<c_tag, c_tag::type>, 
    std::pair<d_tag, d_tag::type> 
> TypeName; 

또는 boost :: fusion :: map을 구현 세부 사항으로 말하면 다음과 같습니다.

// defined once 
template <class Vector> 
struct TemplateType 
{ 
    typedef Vector tags_type; 
    typedef detail::deduce<Vector>::type data_type 
// which for Vector = boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> should be 
// typedef boost::fusion::map< 
// std::pair<a_tag, a_tag::type>, 
// std::pair<b_tag, b_tag::type>, 
// std::pair<c_tag, c_tag::type>, 
// std::pair<d_tag, d_tag::type> 
// > data_type; 

    data_type m_data; 

    template <class T> 
    boost::fusion::result_of::at<T, data_type> at() 
    { 
    return boost::fusion::at<T>(m_data); 
    } 
}; 

// Generated by the macro, filling boost::mpl::vector by iteration 
// the sequence 
typedef TemplateType< boost::mpl::vector<a_tag, b_tag, c_tag, d_tag> > TypeName; 

그런 다음 태그의 하위 집합에서 변환 트릭을 ​​제공하기 만하면됩니다. 전체 하위 집합 만 있으면됩니다. 채우기

template <class Vector> 
TypeName toTypeName(TemplateType<Vector> const& arg) 
{ 
    TypeName result; 
    result.fill(arg); 
    return result; 
} 

는 다음과 같이 정의되고 :

namespace detail 
{ 
    class NoAssign 
    { 
    template <class Pair, class TT> static Do(Pair const&, TTconst&) { } 
    }; 

    class Assign 
    { 
    template <class Pair, class TT> 
    static Do(Pair& p, TTconst& tt) 
    { 
     p.second = tt.at<typename Pair::first_type>(); 
    }; 
    }; 

    template <class Vector> 
    class Filler 
    { 
    public: 
    Filler(TemplateType<Vector> const& ref): m_ref(ref) {} 

    template <class T, class U> 
    void operator()(std::pair<T,U>& p) const 
    { 
     typedef typename boost::mpl::find<T,Vector>::type it; 
     typedef typename boost::mpl::end<Vector>::type end; 

     typedef typename boost::mpl::if< boost::same_type<it,end>, NoAssign, Assign> assign; 

     assign::Do(p, m_ref); 
    } 

    private: 
    TemplateType<Vector> const& m_ref; 
    }; 
} 

template <class Vector> 
template <class OV> 
void TemplateType<Vector>::fill<OV>(TemplateType<OV> const& rhs) 
{ 
    boost::fusion::for_each(m_data, detail::Filler<OV>(rhs)); 
} 

내가 그 문제를 사랑하지만, 물론 일부 템플릿 클래스/메소드를 생성하는 메타 템플릿 Progamming 및 전처리를 모두 사용하도록 강요하고 ... 의미 일부 오랜 해결책과 두통이 있습니다. 그러나 일단 구문이 실제로 (사용자에 대한) 깔끔한 수 있습니다.

+0

- 나는 모든 것을 얻지 못한다. 그러나 나는 이것이 yelsds nice POD 구조체가 내가 필요로하는 membervalues만을 저장하고 있다고 생각하지 않는다고 생각 하는가? – genesys

+0

그들이 POD인지 아닌지는 구현의 문제이며, 퓨전이 커버 뒤에 어떻게 구현되는지 정확히 알지 못합니다. 빠른 테스트는'fusion :: map'이 상응하는 구조체의 2 배 크기라는 것을 증명하는 경향이 있습니다. –

관련 문제