2016-08-12 4 views
4

C++ 템플릿 mixin 구조를 고려할 때 특정 구성 요소와 mixin을 사용하는 함수를 작성하려면 어떻게해야합니까? 이 예에서 withAandBworksWithA()으로 어떻게 할 수 있습니까? 템플릿 mixin을 인수로 가져 오는 방법은 무엇입니까?

struct Base {}; 

template <class T> 
struct HasA : T 
{ 
    int A; 
}; 

template <class T> 
struct HasB : T 
{ 
    int B; 
}; 

void WorksWithA(HasA<Base> &p) 
{ 
    p.A++; 
} 

void WorksWithAandB(HasA<HasB<Base> > &p) 
{ 
    p.A++; 
    p.B++; 
} 

int _tmain(int argc, _TCHAR *argv[]) 
{ 
    HasA<Base> withA; 
    HasA<HasB<Base> > withAandB; 

    WorksWithA(withA); // OK 
    WorksWithAandB(withAandB); // OK 
    WorksWithA(withAandB); // KO, no conversion available 

    return 0; 
} 

심지어 건설 문제, 또는 믹스 인 주문 ( HasB<HasA<Base>>HasA<HasB<Base>>)를 제쳐두고, 내가 템플릿도 그것을 만들기 옆에이 기능을 쓸 수있는 좋은 방법을 볼 수 없습니다.

저는 현재 C++ 11이없는 환경에 있지만, 현대 C++가이 문제에 대한 해결책을 제시한다면 저는 관심을 가질 것입니다.

고맙습니다. 코드가 오류없이 컴파일이 경우

template<typename T> 
void WorksWithA(HasA<T> &p) 
{ 
    p.A++; 
} 

:

답변

2

당신은 HasA로 포장 어떤 클래스를 받아들이는 WorksWithA 템플릿 기능을 할 수 있습니다.

2

함수 템플릿을 만들어야한다고 생각하십니까? HasA<HasB<Base>> 이후

template <class T> 
void WorksWithA(HasA<T> &p) 
{ 
    p.A++; 
} 

template <class T> 
void WorksWithAandB(HasA<HasB<T> > &p) 
{ 
    p.A++; 
    p.B++; 
} 

HasA<Base>로 변환 방법입니다.

+0

감사합니다.나는'HasB '이'Base'에서 유래 되었기 때문에'HasA >'에서'HasA ' – plule

+0

으로 변환 할 수있는 방법이 있기를 바란다. 나는 네가 말한 것처럼 내 대답을 고쳐야한다. HasB '은'Base'에서 파생되어 변환이 가능하지만,'HasA >은'HasA '으로 변환 할 수 없습니다. 인스턴스화 된 모든 템플릿 유형은 서로 다르며 HasA 및 HasA 과 같은 관계형이지만 HasA 및 Has은 완전히 다른 관계입니다. –

1

WorksWithA을 함수 템플릿으로 설정해야합니다. 다른 방법은 없습니다. 그것에 대해 생각하십시오 : WorksWithA 유형의 HasA mixin과 함께 작동합니다. 그것은 단지 템플릿으로 표현 될 수 있습니다. 당신이 WithA 인터페이스를 구현하는 모든 클래스의 객체와 WorkWithA를 호출 할 수 있습니다 여기에

struct HasA 
{ 
    int A; 
    virtual ~HasA() = default; 
}; 

struct HasB 
{ 
    int B; 
    virtual ~HasB() = default; 
}; 

struct HasAB : HasA, HasB 
{ 
}; 

struct Base : HasAB 
{}; 

void WorksWithA(HasA &p) 
{ 
    p.A++; 
} 

void WorksWithAandB(HasAB &p) 
{ 
    p.A++; 
    p.B++; 
} 

WorksWithAandB :

1

또한, 경우에 HasAHasB이 인터페이스의 의미를 가지고이 문제를 해결하기 위해 상속을 사용하는 것이 좋습니다 모든 클래스의 객체는 HasAB 인터페이스를 구현합니다.

PS : 불행하게도,이 예에서, 그것은 HasAB에서 상속없이 모두 HasAHasB를 구현하는 클래스의 객체와 WorksWithAandB를 호출하는 것은 불가능하지만,이 템플릿과 SFINAE를 사용하여 해결 될 수있다.

+0

고마워요, 저건 실제로 제 현재의 디자인이고, 저는이 "HaveAB"을 갖는 더 좋은 방법을 찾고 있습니다. SFINAE 개념을 살펴볼 것입니다. – plule

2

다른 사람들이 지적했듯이이 기능은 템플릿으로 사용하는 것이 좋습니다. 다른 유형의 호출 WorksWithAAndB 여기

template<class B> 
void WorksWithA(HasA<B> &p) 
{ 
    p.A++; 
} 

template<class B> 
void WorksWithB(HasA<B> &p) 
{ 
    p.B++; 
} 

template<class Has> 
void WorksWithAandB(Has &p) 
{ 
    WorksWithA(p); 
    WorksWithB(p); 
} 

: 당신이 그것에있는 동안 그러나, 당신은 또한 몇 가지 코드의 중복을 제거 할 수 있습니다. 따라서 :

  1. 코드를 재사용하고 있습니다.
  2. WorksWithAAndB에 전달 된 유형에 대해 WorksWithAWorksWithB에 전달 된 유형 유형의 컴파일러 검사를 다시 사용하고 있습니다.
관련 문제