使用lambda和std :: function的C++ 11类型推断

Ale*_*son 8 c++ lambda type-inference c++11

我有以下代码片段,虽然完全无关紧要,但它说明了我试图在更通用的代码中使用的模式.

template<typename InT, typename ResT>
ResT unary_apply( InT val, std::function<ResT(InT)> fn )
{
    return fn(val);
}
Run Code Online (Sandbox Code Playgroud)

我希望能够使用函数指针,函子,lambdas等来调用unary_apply:因此使用它std::function来抽象所有.

当我尝试以下列方式使用上述内容时,C++(g ++ 4.7)无法执行相关的类型推断:

double blah = unary_apply( 2, []( int v ) { return 3.0 * v; } );
Run Code Online (Sandbox Code Playgroud)

失败了

src/fun.cpp:147:75: error: no matching function for call to ‘unary_apply(int, test()::<lambda(int)>)’
src/fun.cpp:147:75: note: candidate is:
src/fun.cpp:137:6: note: template<class InT, class ResT> ResT unary_apply(InT, std::function<ResT(InT)>)
src/fun.cpp:137:6: note:   template argument deduction/substitution failed:
src/fun.cpp:147:75: note:   ‘test()::<lambda(int)>’ is not derived from ‘std::function<ResT(double)>’
Run Code Online (Sandbox Code Playgroud)

而且我发现我必须明确指定模板参数(实际上我认为它只是不可推断的返回类型):

double blah = unary_apply<int, double>( 2, []( int v ) { return 3.0 * v; } );
Run Code Online (Sandbox Code Playgroud)

我对C++ 11中的类型推理规则并不熟悉,但上述行为看起来确实合理(我可以看出通过内部机制推断std::function可能是一个很大的问题).我的问题是:是否有可能重新编写unary_apply上面的函数以保持相同的灵活性(就可以作为第二个参数传递的函数/函子的类型而言),同时还提供了更多类型推断的线索,我不必在通话点明确提供模板参数?

Cat*_*lus 10

更多鸭子应该工作:

template <typename T, typename F>
auto unary_apply(T&& val, F&& func) -> decltype(func(val)) {
    return func(std::forward<T>(val));
}
Run Code Online (Sandbox Code Playgroud)

  • @AlexWilson:这里的问题不是模板或`decltype`的推理规则可能不同,而是它的使用方式.模板需要类型的完美匹配(只允许使用const-volatile限定符),在您的情况下,函数采用`std :: function <?>`但参数是lambda.`std :: function <>`可以用不同的东西构造,包括lambda,但它们是不同的类型,需要在该上下文中不允许的转换.在`decltype`的情况下,类型`F`被推断为lambda的类型. (3认同)