이 문제를 해결하기위한 내 전략은 몇 가지 수준의 간접 지정을 사용하는 것입니다.
- 지퍼 < 인수 ...> 상속에 의해 기능 process_zipper_arguments에 인수의 치료를 전달합니다 :
이
예 :
template < typename... Args >
struct zipper : zipper < typename process_zipper_arguments <Args...>::type > {};
- 가 추적하는
template < typename... Args > struct typelist {}
를 사용 상속 할 오브젝트 유형.
- 위해
중복 부모 유형을 제거 할 수있는 실제 상속을 할 struct zipper < typelist <Args...> >: public virtual Args...
전문은,이 개 도우미 기능 process_zipper_arguments
에 사용됩니다
is_in < CandidateType, typelist<Args...> >::type
이 true_type
또는 false_type
중 하나이며 정의 할 수 있습니다 재귀 적으로
add_unique < CandidateType, typelist<Args...> >::type
은 typelist <...>
이며 CandidateType이 추가되거나 추가되지 않습니다. 그것을 결정하기 위해 is_in
이 호출됩니다.
다음은 적어도 g ++ (GCC) 4.6.3과 --std = C++ 0x로 컴파일 된 완전한 코드입니다. 그것에 대한 비판은 환영합니다.
// Forward declarations
template < typename... Args >
struct zipper;
// Two types meaning true and false
struct true_type {};
struct false_type {};
// The only purpose of this struct is to be associated with Types...
template < typename... Types >
struct typelist {};
// ===================================================
// is_in < type, typelist<...> >::type
// is true_type if type is in typelist
// is false_type if type is not in typelist
// Assume TElement is not in the list unless proven otherwise
template < typename TElement, typename TList >
struct is_in {
typedef false_type type;
};
// If it matches the first type, it is definitely in the list
template < typename TElement, typename... TTail >
struct is_in < TElement, typelist < TElement, TTail... > >
{
typedef true_type type;
};
// If it is not the first element, check the remaining list
template < typename TElement, typename THead, typename... TTail >
struct is_in < TElement, typelist < THead, TTail... > >
{
typedef typename is_in < TElement, typelist <TTail...> >::type type;
};
// ===================================================
// add_unique < TNew, typelist<...> >::type
// is typelist < TNew, ... > if TNew is not already in the list
// is typelist <...> otherwise
// Append a type to a type_list unless it already exists
template < typename TNew, typename TList,
typename Tis_duplicate = typename is_in < TNew, TList >::type
>
struct add_unique;
// If TNew is in the list, return the list unmodified
template < typename TNew, typename... TList >
struct add_unique < TNew, typelist <TList...>, true_type >
{
typedef typelist <TList...> type;
};
// If TNew is not in the list, append it
template < typename TNew, typename... TList >
struct add_unique < TNew, typelist <TList...>, false_type >
{
typedef typelist < TNew, TList... > type;
};
// ===================================================
// process_zipper_arguments <Args...>::type
// returns a typelist of types to be inherited from.
//
// It performs the following actions:
// a) Unpack zipper<...> and typelist <...> arguments
// b) Ignore values that are already in the list
template < typename... Args >
struct process_zipper_arguments;
// Unpack a zipper in the first argument
template < typename... ZipperArgs, typename... Args >
struct process_zipper_arguments < zipper <ZipperArgs...>, Args... >
{
typedef typename process_zipper_arguments < ZipperArgs..., Args... >::type type;
};
// Unpack a typelist in the first argument
template < typename... TypeListArgs, typename... Args >
struct process_zipper_arguments < typelist <TypeListArgs...>, Args... >
{
typedef typename process_zipper_arguments < TypeListArgs..., Args... >::type type;
};
// End the recursion if the list is empty
template < >
struct process_zipper_arguments < >
{
typedef typelist < > type;
};
// Construct the list of unique types by appending them one by one
template < typename THead, typename... TTail >
struct process_zipper_arguments < THead, TTail... >
{
typedef typename
add_unique < THead,
typename process_zipper_arguments <TTail...>::type
>::type type;
};
// ===================================================
// The zipper class that you might want
// If the list of types is not yet known, process it.
// The inheritance is ugly, but there is a workaround
template < typename... Args >
struct zipper : zipper < typename process_zipper_arguments <Args...>::type >
{
// // Instead of inheriting, you can use zipper as a factory.
// // So this:
// typedef zipper < meas2, zipper < meas1, meas > > mymeas;
// // Turns to:
// typedef typename zipper < meas2, zipper < meas1, meas > >::type mymeas;
typedef zipper < typename process_zipper_arguments <Args...>::type > type;
};
// If the list of types is known, inherit from each type
template < typename... Args >
struct zipper < typelist <Args...> >
: public virtual Args...
{};
// ===================================================
// Short usage demo, replace with your own code
struct meas {
int i;
};
struct meas2 {
int j;
};
struct meas3 {
int k;
};
typedef zipper < meas, meas, meas3 > meas_type;
typedef zipper < meas2, meas_type, meas2 > meas_type2;
typedef typename zipper <meas_type2>::type nicer_meas_type2;
int main (int, char**)
{
meas * m = new meas_type2;
meas_type2 n;
nicer_meas_type2 o;
return 0;
}
가합니다 (return 0;
줄에 중단 점) 결과 다음을 제공합니다 디버깅 :
(gdb) print *m
$1 = {i = 0}
(gdb) print n
$2 = {<zipper<typelist<meas, meas3, meas2> >> = {<meas> = {i = 4196320}, <meas3> = {k = 0}, <meas2> = {j = 0},
_vptr.zipper = 0x400928}, <No data fields>}
(gdb) print o
$3 = {<meas> = {i = 4195719}, <meas3> = {k = 0}, <meas2> = {j = 1}, _vptr.zipper = 0x4009a8 <VTT for zipper<typelist<meas, meas3, meas2> >>}
당신은 평평뿐만 아니라 중복을 제거 할. – Nawaz
정확히 @Nawaz! –
질문 1에 대해, 'zipper'로 변환하겠습니까? 당신은'meas' 부분을 떨어 뜨린 것 같습니다. –