pon*_*ong 12 c++ c++11 visual-c++-2015
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
}
Run Code Online (Sandbox Code Playgroud)
foo和bar之间的唯一区别是foo具有可变参数.不知何故,编译器能够将lambda转换为bar中的std :: function .
据我所知,模板类型推导不考虑类型转换.那么两个都不应该失败吗?
Cal*_*eth 10
您没有任何类型参数的扣除bar,它们是完全指定的.
你仍然有包的尾部推断foo,并且失败因为lambda不是std::function.
template<typename ReturnT, typename... ParamT>
void foo(std::function<ReturnT(ParamT...)> callback)
{}
Run Code Online (Sandbox Code Playgroud)
现在,foo<int,int>是foo<ReturnT=int, ParamsT starts with {int}>.
它没有完全说明ParamT.实际上,没有办法完全指定ParamT.
作为未完全指定的模板,演绎发生并失败.它不会尝试"如果我只是假设包装不再进一步".
你可以解决这个问题:
template<typename ReturnT, typename... ParamT>
void foo(block_deduction<std::function<ReturnT(ParamT...)>> callback)
{}
Run Code Online (Sandbox Code Playgroud)
其中block_deduction的样子:
template<class T>
struct block_deduction_helper { using type=T; }:
template<class T>
using block_deduction = typename block_deduction_helper<T>::type;
Run Code Online (Sandbox Code Playgroud)
现在扣除在foo第一个参数上被阻止了.
你的代码有效.
当然,如果你传入std::function它将不再自动推断参数.
请注意,推断类型擦除类型的类型std::function通常是代码味道.
将两者替换为:
template<class F>
void bar(F callback)
{}
Run Code Online (Sandbox Code Playgroud)
如果你必须获得参数,请使用函数特性助手(SO上有很多).如果你只需要返回值,那么有些std特征已经可以解决了.
在c ++ 17中,您可以这样做:
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);
}
Run Code Online (Sandbox Code Playgroud)
使用c ++ 17演绎指南功能.
| 归档时间: |
|
| 查看次数: |
324 次 |
| 最近记录: |