如果模板没有可变参数,则将Lambda推导为std :: function [英] Lambda is deduced to std::function if template has no variadic arguments

查看:95
本文介绍了如果模板没有可变参数,则将Lambda推导为std :: function的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

template<typename ReturnT, typename... ParamT>
void foo(std::function<ReturnT(ParamT...)> callback)
{}

template<typename ReturnT, typename ParamT>
void bar(std::function<ReturnT(ParamT)> callback)
{}

main()
{    
    foo<int, int>([](int x){ return x; });  // no instance of function 
                                            //   template matches argument list
    bar<int, int>([](int x){ return x; });  // OK
}

foo bar 之间的唯一区别是 foo 具有可变参数.编译器可以通过某种方式将lambda转换为 bar 中的std :: function.

The only difference between foo and bar is that foo has variadic arguments. Somehow the compiler is able to convert the lambda to a std::function in bar.

据我了解,模板类型推导不考虑类型转换.所以都不应该都失败吗?

To my understanding, template type deduction doesn't consider type conversions. So shouldn't both fail?

推荐答案

template<typename ReturnT, typename... ParamT>
void foo(std::function<ReturnT(ParamT...)> callback)
{}

现在,foo<int,int>foo<ReturnT=int, ParamsT starts with {int}>.

它没有完全指定ParamT.实际上,没有办法完全指定ParamT.

It does not fully specify ParamT. In fact, there is no way to fully specify ParamT.

作为不完整指定的模板,推导发生并且失败.它不会尝试如果我只是假设包装不会继续下去怎么办".

As an incompletely specified template, deduction occurs, and fails. It doesn't try "what if I just assume the pack doesn't go any further".

您可以通过以下方法解决此问题:

You can fix this with:

template<typename ReturnT, typename... ParamT>
void foo(block_deduction<std::function<ReturnT(ParamT...)>> callback)
{}

其中block_deduction如下:

template<class T>
struct block_deduction_helper { using type=T; }:
template<class T>
using block_deduction = typename block_deduction_helper<T>::type;

现在推导被阻止在foo的第一个参数上.

now deduction is blocked on foo's first argument.

您的代码有效.

当然,如果您传入std::function,它将不再自动推论参数.

Of course, if you pass in a std::function it will no longer auto-deduce arguments.

请注意,推导类型擦除类型(如std::function)的类型通常是代码异味.

Note that deducing the type of a a type erasure type like std::function is usually code smell.

同时替换为:

template<class F>
void bar(F callback)
{}

如果必须获取参数,请使用函数特征助手(在SO上有很多).如果您只需要返回值,那么已经有std个特征已经解决了.

if you must get arguments, use function traits helpers (there are many on SO). If you just need return value, there are std traits that already work that out.

c ++ 17 您可以执行以下操作:

In c++17 you can do this:

tempate<class R, class...Args>
void bar( std::function<R(Args...)> f ) {}
template<class F>
void bar( F f ) {
  std::function std_f = std::move(f);
  bar(std_f);
}

使用演绎指南功能.

这篇关于如果模板没有可变参数,则将Lambda推导为std :: function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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