2014-11-03 3 views
2

Для следующего кода:Неоднозначность частичной специализации шаблона с varadic шаблоном

template <typename T> 
struct IsOneOf<T,T> { const static bool True = true; }; 
template <typename T, typename ... Ts> 
struct IsOneOf<T,any_of<T,Ts ...> > { const static bool True = true;}; 
template <typename T, typename T2,typename ... Ts> 
struct IsOneOf<T,any_of<T2,Ts ...> > { 
    const static bool True = IsOneOf<T,T2>::True || 
          IsOneOf<T,any_of<Ts ...> >::True; 
}; 
template <typename T1, typename ... Ts1, typename ... Ts2> 
struct IsOneOf< any_of<T1,Ts1 ...>, any_of<Ts2 ...> > { 
    const static bool True = IsOneOf<T1,any_of<Ts2 ...> >::True && 
          IsOneOf<any_of<Ts1...>, any_of<Ts2 ...> >::True; 
}; 

Последняя специализация предназначена для переопределения других, но я получаю неоднозначные ошибки шаблона создания экземпляра для IsOneOf<any_of<int>,any_of<int,double,float>>::True. Может кто-нибудь предложить способ преодолеть это?

+0

Где базовое (неспециализированное) определение шаблона? Также было бы неплохо иметь 'any_of', определенный в вопросе, даже если он является пустым или неполным, как я подозреваю. – Casey

+0

В чем смысл этого? Почему бы не простой рекурсивный 'IsOneOf '? – Walter

+0

Привет, Casey, any_of - это просто пустая структура в этой точке. Цель состоит в том, чтобы определить, является ли любая группа any_of частью другого, т. Е. Any_of должно принадлежать любому из . –

ответ

1

Последняя специализация IsOneOf<any_of<T1,Ts1...>, any_of<Ts2...>> не более специализирована, чем IsOneOf<T,any_of<T2,Ts...>>, так как если Ts2 - пустой список, он не может соответствовать последнему. Я думаю, что вы хотите этого, либо вместо или в дополнение к вашей последней специализации:

template <typename T1, typename ... Ts1, typename T2, typename ... Ts2> 
struct IsOneOf< any_of<T1,Ts1 ...>, any_of<T2,Ts2 ...> > 
{ 
    const static bool True = IsOneOf<T1, any_of<T2,Ts2...>>::True && 
          IsOneOf<any_of<Ts1...>, anyOf<T2,Ts2...>>::True; 
}; 

Вы также есть проблемы с IsOneOf<any_of<int,double>, any_of<int,double>>, так как в этом случае ваш IsOneOf<T,T> неоднозначна с этим в общем случае. Таким образом, вы можете вырезать, что от указав пересечение:

template <typename T1, typename ... Ts> 
struct IsOneOf< any_of<T1,Ts ...>, any_of<T1,Ts ...> > 
{ 
    const static bool True = true; 
}; 

Вам также понадобится база дел, связанных с типом any_of<>, если вы уже не имеете их.

+0

Спасибо, aschelper, это работает! –

0

В чем смысл этого сложного и непрозрачного дизайна? Если идея в том, что IsOneOf<A,B...>::value является true тогда и только тогда, когда по крайней мере один из B типов являются такой же, как A, то простой рекурсивной конструкцией (избегая вспомогательные вещества, такие как any_of), такие как

// is_one_of<A,B1,B2,...>::value == is_same<A,B1>::value || is_same<A,B2>::value ... 
template<typename A, typename... B> 
struct is_one_of; 

// case of empty pack B... 
template<typename A> 
struct is_one_of<A> : std::false_type {}; 

// general case: recurse 
template<typename A, typename B1, typename... B> 
struct is_one_of<A,B1,B...> 
: std::integral_constant<bool, std::is_same<A,B1>::value || is_one_of<A,B...>::value> {}; 

является preferrable, требующим только две специализации (для пустого пакета B s и рекурсивного случая). Более того, is_one_of являются хорошими гражданами C++, будучи производными от std::integral_constant<bool,C>.

Смежные вопросы