加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 如何推断出变量参数后的模板参数?

发布时间:2020-12-16 10:24:08 所属栏目:百科 来源:网络整理
导读:我有以下模板功能: template typename...Args,typename Funcvoid call(const char *name,Args...args,Func f){ f(3);} 当我尝试使用它时,就像 call("test",1,2,3,[=](int i) { std::cout i; }); 编译器抱怨它无法推断模板参数Func. 知道args可以是除函数指
我有以下模板功能:

template <typename...Args,typename Func>
void call(const char *name,Args...args,Func f)
{
        f(3);
}

当我尝试使用它时,就像

call("test",1,2,3,[=](int i) { std::cout<< i; });

编译器抱怨它无法推断模板参数Func.
知道args可以是除函数指针之外的任何类型,如何解决这个问题.

解决方法

写get_last,它提取参数包的最后一个元素.

叫它f.致电f.

举个例子,

template<typename T0>
auto get_last( T0&& t0 )->decltype(std::forward<T0>(t0))
{
  return std::forward<T0>(t0);
}
template<typename T0,typename... Ts>
auto get_last( T0&& t0,Ts&&... ts )->decltype(get_last(std::forward<Ts>(ts)...))
{
  return get_last(std::forward<Ts>(ts)...);
}

如果您不关心重载解析,只需调用get_last并将其视为仿函数就足够了:

template <typename...Args>
void call(const char *name,Args...&& args)
{
    auto&& f = get_last(std::forward<Args>(args)...);
    f(3);
}

下一步将是做一些SFINAE enable_if魔法,以便在最后没有传递有效仿函数时使调用失败:但是,这可能是矫枉过正.

要检测f(3)是否有效,可以使用一个简单的traits类:

// trivial traits class:
template<typename T>
struct is_type:std::true_type {};

template<typename Functor,typename=void>
struct can_be_called_with_3:std::false_type {}

template<typename Functor>
struct can_be_called_with_3<Functor,typename std::enable_if<
    std::is_type< decltype(
      std::declval<Functor>(3)
    ) >::value
  >::type
>:std::true_type {}

这很傻.如果您对传入类型的要求更复杂(例如,您希望使用参数调用它),则必须使用更高级的traits类.

然后你用以下方式扩充呼叫:

template <typename...Args>
auto call(const char *name,Args...&& args)
  -> typename std::enable_if<
       can_be_called_with_3< decltype( get_last(std::forward<Args>(args)... ) ) >::value
     >::type
{ /* body unchanged */ }

这是非常迟钝的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读