我有以下类型特征:
var d = new Date('2017-02-22T22:00');
d.setMonth(d.getMonth()+1)
console.log(d);
对于大多数用例来说,查找函数所使用的参数数量非常有用,但是对于一个常见情况它会失败:
template <class T>
struct Arity : Arity<decltype(&T::operator())> {};
template <class T, class R, class... Args>
struct Arity<R(T::*)(Args...)> {
static constexpr auto value = sizeof...(Args);
};
template <class T, class R, class... Args>
struct Arity<R(T::*)(Args...) const> {
static constexpr auto value = sizeof...(Args);
};
template <class R, class... Args>
struct Arity<R(*)(Args...)> {
static constexpr auto value = sizeof...(Args);
};
我认为通常不能为任何模板化的函数/运算符()使其工作,因为根据作为模板类型传递的类型/值,可以选择不同的重载,或者可能没有可用的重载一点都不此外,无法知道要传递的有效类型和值作为模板参数。但是,我仍然希望这适用于lambda采用auto l1 = [](int, double){};
Arity<decltype(l1)>::value; // works, 2
auto l2 = [](auto, auto){};
Arity<decltype(l2)>::value; // error: Reference to overloaded function could not be resolved; did you mean to call it?
参数的常见情况。有没有办法让这个更强大并覆盖带有自动参数的lambda?
答案 0 :(得分:4)
我想我在这里实现了一半的解决方案。仅适用于固定数量的参数,但对于大多数不应该成为问题的应用程序。此外,它可能是高度简化的,但我的大脑现在还没有陷入棘手的SFINAE。
template <
class, std::size_t N,
class = std::make_index_sequence<N>,
class = void_t<>
>
struct CanCall : std::false_type { };
template <class F, std::size_t N, std::size_t... Idx>
struct CanCall<
F, N,
std::index_sequence<Idx...>,
void_t<decltype(std::declval<F>()((Idx, std::declval<Any const&&>())...))>
> : std::true_type { };
CanCall<F, N>
将返回F
是否可以使用任意类型的N
参数进行调用。 Any
辅助类型具有模板化的隐式转换运算符,允许它转换为任何所需的参数类型。
template <class F, std::size_t N = 0u, class = void>
struct Arity : Arity<F, N + 1u, void> { };
template <class F, std::size_t N>
struct Arity<F, N, std::enable_if_t<CanCall<F, N>::value>>
: std::integral_constant<std::size_t, N> { };
template <class F>
struct Arity<F, MAX_ARITY_PROBING, void>
: std::integral_constant<std::size_t, ARITY_VARIADIC> { };
Arity<F>
只检查是否可以使用零,一,二......参数调用F
。第一次正面检查获胜。如果我们达到MAX_ARITY_PROBING
个参数,Arity
就会失效,并假设该函数是可变参数,或根本不是函数。
答案 1 :(得分:2)
我认为你不能在你的参数类型为auto
的用例中使用lambda函数。这些lambda函数的operator()
函数很可能是使用函数模板实现的。
因此,decltype
不能用于:
auto l2 = [](auto, auto){};
Arity<decltype(l2)>::value;
有关此主题的更多信息,请参阅this answer to another SO question。