我定义了一个像这样的方法:
template <class ArgT>
void foo(ArgT arg, ::boost::function< void(ArgT) > func)
{
    func(arg);
}
并像这样使用 - 例如 - :
foo(2, [](int i) -> void { cout << i << endl; });
为什么编译器不能推断出类型,因为它肯定是一个int?
我得到'void foo(ArgT,boost::function<void(ArgT)>)' : could not deduce template argument for 'boost::function<void(ArgT)>' from 'anonymous-namespace'::<lambda0>'.
ild*_*arn 10
虽然C++ lambdas是严格单态的,但它们只是函数对象(aka functor)的简写,而且一般来说,functor可以是多态的; 即,他们的呼叫运营商可能过载或模板化.因此,仿函数(以及lambdas)永远不会隐式转换为模板std::function<>(或boost::function<>)实例,因为operator()仿函数的参数类型不能自动推断.
为了略微区别它,lambda表达式的自然类型是一个带有无参数构造函数和operator()带签名的仿函数void operator ()(int) const.然而,显而易见的事实可能是你和我,它不能自动推断ArgT应该解决,int因为lambdas是仿函数和仿函数operator()可以重载和模板.
TL; DR:你想要的是不可能的.
你想从lambda函数的转换boost::function<void(ArgT)>,其中ArgT的被推导出来.作为一般规则,您不能在函数的同一参数中进行类型推导和转换:在推导模板参数时不会发生转换.
这背后的原因如下.这里涉及三种类型:(1)模板参数,(2)函数参数类型,(3)传递的对象类型.其中两种类型(1和2)可以相互推断,但两者都是未知的.如果编译器可以假设2和3是相同的类型,问题就解决了,但是如果所有编译器都知道3可以转换为2,则可能存在任意数量的可能解决方案,并且编译器不希望解决问题.在实践中,我们知道在这种特殊情况下只有一种可能的解决方案,但标准并没有对案例进行区分.
上述规则适用于所有可推导的上下文,即使模板参数可以从另一个函数参数推导出来.这里的解决方案是使相关的函数参数成为不可推导的上下文,即编译器永远不会尝试从函数参数推导出模板参数的上下文.这可以按如下方式完成:
template <class T> struct identity { typename T type; };
template <class ArgT>
void foo(ArgT arg, typename identity<::boost::function<void(ArgT)>>::type func)
{
  func(arg);
} 
| 归档时间: | 
 | 
| 查看次数: | 1663 次 | 
| 最近记录: |