如何找到模板函数采用的参数数量? [英] How can I find the number of arguments a template function takes?

查看:29
本文介绍了如何找到模板函数采用的参数数量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类型特征:

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);
};

在大多数用例中查找函数采用的参数数量非常有效,但对于一种常见情况则失败:

Which works great to find the number of arguments a function takes for most use cases, but it fails for one common case:

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?

我相信通常不可能对任何模板化函数/operator() 进行这项工作,因为根据作为模板类型传递的类型/值,可以选择不同的重载,或者可能根本没有可用的重载.此外,无法知道要作为模板参数传递的有效类型和值.但是,我仍然希望这适用于采用 auto 参数的 lambda 的常见情况.有什么方法可以使它更健壮并覆盖采用自动参数的 lambda 表达式?

I believe it's impossible to generally make this work for any templated function / operator() because depending on the types/values passed as template types, a different overload could be selected, or perhaps no overload may be available at all. Also, there's no way to know what valid types and values to pass as template arguments. But still, I want this to work for the common case of a lambda taking auto arguments. Is there any way to make this more robust and cover lambdas which take auto arguments?

推荐答案

我想我在这里完成了一半的解决方案.仅适用于固定数量的参数,但对于大多数应用程序来说应该不是问题.此外,它可能高度简化,但我的大脑现在还没有进入棘手的 SFINAE.

I guess I achieved half of a solution here. Only works up to a fixed number of parameters, but for most applications that shouldn't be an issue. Also, it's probably highly simplifiable but my brain is not into tricky SFINAE right now.

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 参数调用.Any 辅助类型具有模板化的隐式转换运算符,允许它变形为任何所需的参数类型.

CanCall<F, N> will return whether F is callable with N parameters of arbitrary type. The Any helper type has templated implicit conversion operators that allows it to morph into any desired parameter type.

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.第一个正面检查获胜.如果我们达到 MAX_ARITY_PROBING 参数,Arity 会跳出并假设该函数要么是可变参数,要么根本不是函数.

Arity<F> just checks whether an F can be called with zero, one, two... parameters. First positive check wins. If we reach MAX_ARITY_PROBING parameters, Arity bails out and supposes that the function is either variadic, or is not a function at all.

在 Coliru 上观看直播

这篇关于如何找到模板函数采用的参数数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆