将"模板<类型名 T>zero()"扩展/专用为可调用的"T"

Extending/specializing `template<typename T>zero()` to invocable `T`

本文关键字:专用 扩展 调用 gt lt 模板 类型 zero      更新时间:2023-10-16

我正在尝试定义一个函数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 表达式(,这将不起作用。