考虑这个简单的示例代码:
#include <functional>
#include <iostream>
void f(bool _switch) {
std::cout << "Nothing really" << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
return 0;
}
编译失败:
$ g++ --std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:33: error: call of overloaded ‘f(main(int, char**)::<lambda(int)>)’ is ambiguous
main.cpp:15:33: note: candidates are:
main.cpp:6:6: note: void f(bool)
main.cpp:10:6: note: void f(std::function<double(int)>)
但是,如果我用一个引用参数替换第二个函数,它就可以正常编译。如果它被 const 引用替换,它会再次失败。
所以我对这个例子有一些疑问:
- 为什么 lambda 函数首先可以隐式转换为
bool
? - 为什么采用 std::function 引用可以解决歧义?
- 对我来说最重要的是,我该如何避免这个问题?我需要第二个函数来获取 std::function 的(拷贝)或对它的 const 引用。
最佳答案
可以将没有捕获的 lambda 函数转换为常规函数指针,然后将其标准转换为 bool。
如果您通过非常量引用获取 std::function
,那么这会将它排除在候选者之外,因为将 lambda 转换为 std::function
需要临时的,临时的不能绑定(bind)到非常量引用。这只留下 f(bool)
作为候选,所以没有歧义。
有很多方法可以避免歧义。例如,您可以先创建一个 std::function
变量:
std::function<double(int)> g = [](int _idx){ return 7.9;};
f(g);
或者你可以转换 lambda:
f(std::function<double(int)>([](int _idx){return 7.9;}));
你可以有一个辅助函数:
template<typename T>
std::function<T> make_function(T *f) { return {f}; }
int main ( int argc, char* argv[] ) {
f(make_function([](int _idx){ return 7.9;}));
return 0;
}
或者您可以获取您感兴趣的特定功能:
int main ( int argc, char* argv[] ) {
void (*f_func)(std::function<double(int)>) = f;
f_func([](int _idx){ return 7.9;});
return 0;
}
关于C++11 Lambda 函数隐式转换为 bool 与 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23162654/