我正在尝试定义一个函数template<typename T> zero()
并将其专门用于各种情况。
zero<T>()
应该返回
static T::zero()
是否存在。- 否则
static_cast<T>(0)
是否定义了。
到目前为止一切顺利,如下所述。
现在我想以合理的方式将模板扩展到任何可隐式转换为形式std::function<Y(X...)>
类型的T
,并且应该返回相应的零返回函数[](X...){return zero<Y>();}
最好的方法是什么?
namespace hidden {
// tag dispatching
template<int r>
struct rank : rank<r - 1> {};
template<>
struct rank<0> {};
template<typename T>
auto zero(rank<2>) -> decltype(T::zero()) {
return T::zero();
}
template<typename T>
auto zero(rank<1>) -> decltype(static_cast<T>(0)) {
return static_cast<T>(0);
}
// This is where I need help
template<typename T>
auto zero(rank<0>) -> std::enable_if_t</* T is implicitly convertible to std::function<Y(X...)> */,T> {
using Y = // the type returned when an instance of T is invoked
return []() {
return zero<Y>();
};
}
}
template<typename T>
auto zero() { return hidden::zero<T>(rank<10>{}); }
编辑:
我现在已诉诸于重复以下内容,为每个预期的签名提供具体的签名:
template<typename T>
auto zero(rank<0>)
-> std::enable_if_t<std::is_assignable<std::function<double(double)>, T>::value
, std::function<double(double)>> {
using Y = double;
return []() {
return zero<Y>();
};
}
但我希望可以用模板魔法代替复制粘贴。
在 c++17 中,演绎指南为std::function
:
template <typename T,
typename F = decltype(std::function{std::declval<T>()}),
typename Y = typename F::result_type>
F zero(rank<0>) {
return [](auto&&...) {
return zero<Y>(rank<10>{});
};
}
演示
在 c++14 中,你需要自己编写这个特征。
但请注意,如果T::operator()
重载或表示函数模板(包括通用 lambda 表达式(,这将不起作用。