使用可变参数模板的模糊部分模板专业化

时间:2014-11-03 19:43:56

标签: c++ c++11

以下代码:

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的模糊实例化错误。有人可以建议一种方法来克服这个问题吗

2 个答案:

答案 0 :(得分: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<>,那么您还需要处理{{1}}类型的基本案例。

答案 1 :(得分:0)

这个复杂而不透明的设计的重点是什么?如果IsOneOf<A,B...>::valuetrue的想法当且仅当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> {};

是首选的,只需要两个特化(对于B的空包和递归情况)。此外,is_one_of来自std::integral_constant<bool,C>,是优秀的C ++公民。