首先,我們需要一個元函數可以告訴我們表達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);
這將調用Evaluate
所有類型T
在Types
爲此CanEvaluate<InputType>::eval<T>::value == true
,並返回||的結果。
你的構造函數本身不應該是模板。 –
'std :: get <0>'是一個例子,還是你真的想迭代每個元素並調用'Evaluate'(給定它們有方法)? – 0x499602D2
如果更多元素匹配會怎樣? – jrok