首先,我们需要一个元函数,它可以告诉我们表达式declval<T>().Evaluate(input)
对于给定类型是否有意义T
。
我们可以使用 SFINAE 和 decltype 来做到这一点:
template<class ... Arguments>
struct CanEvaluate
{
template<class T, class Enable = void>
struct eval : std::false_type {};
template<class T>
struct eval<T,
decltype( void( std::declval<T>().Evaluate(std::declval<Arguments>() ... ) ) ) > : std::true_type {};
};
现在我们可以编写一个类MultiEvaluateFromTuple
。
template<class TupleType, class ... InputTypes>
struct MultiEvaluateFromTuple
{
private:
template<int I,int S,class Dummy = void>
struct CheckEvaluate : CanEvaluate<InputTypes...>::template eval<typename std::tuple_element<I,TupleType>::type> {};
//We need this because we can't instantiate std::tuple_element<S,TupleType>
template<int S> struct CheckEvaluate<S,S> : std::false_type {};
// Forward to the next element
template<int I,int S, class Enabler = void>
struct Impl {
static bool eval(const TupleType & r, const InputTypes & ... input) {
return Impl<I+1,S>::eval(r,input...);
}
};
// Call T::Evalute()
template<int I,int S>
struct Impl<I,S, typename std::enable_if<CheckEvaluate<I,S>::value>::type> {
static bool eval(const TupleType & r, const InputTypes & ... input) {
bool Lhs = std::get<I>(r).Evaluate(input...);
bool Rhs = Impl<I+1,S>::eval(r,input...);
return Lhs || Rhs;
}
};
//! Termination
template<int S>
struct Impl<S,S> {
static bool eval(const TupleType & r, const InputTypes & ... input) {
return false;
}
};
public:
static bool eval(const TupleType & r,const InputTypes & ... input) {
return Impl<0, std::tuple_size<TupleType>::value>::eval(r,input...);
}
};
用法:
return MultiEvaluateFromTuple<std::tuple<Types...>,T>::eval(list,input);
这将调用forEvaluate
中的所有类型T
,并返回 || 的结果。Types
CanEvaluate<InputType>::eval<T>::value == true