C ++ 11 Lambda函数隐式转换为bool vs.std :: function [英] C++11 Lambda functions implicit conversion to bool vs. std::function
问题描述
考虑以下简单示例代码:
Consider this simple example code:
#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引用,它将失败.
However if I replace the second function with a reference argument it compiles fine. And again if it is replaced by a const reference it fails.
所以我对这个例子有一些疑问:
So I have some questions concerning this example:
- 为什么首先将lambda函数隐式转换为
bool
? - 为什么要使用std :: function引用来解决歧义?
- 对我来说最重要的是,如何避免这个问题?我需要第二个函数采用std :: function(的a副本)或对其的const引用.
推荐答案
namespace details{
template<class Sig,class=void>
struct invoke {};
template<class F, class...Args>
struct invoke<F(Args...),decltype(void(
std::declval<F>()(std::declval<Args>()...)
))>{
using type=decltype(std::declval<F>()(std::declval<Args>()...));
};
}
template<class Sig>struct invoke:details::invoke<Sig>{};
template<typename Sig, typename T, typename=void>
struct invoke_test:std::false_type {};
template<typename R, typename...Args, typename T>
struct invoke_test<R(Args...), T,
typename std::enable_if<
std::is_convertible<
typename invoke<T(Args...)>::type,
R
>::value
>::type
>:std::true_type {};
template<typename...Args,typename T>
struct invoke_test<void(Args...),T,
decltype( void( typename invoke<T(Args...)>::type ) )
>:std::true_type{};
template<typename Sig, typename T>
constexpr bool invokable() {
return invoke_test<Sig,T>::value;
}
这为我们提供了一个伪概念invokable
.
this gives us a pseudo-concept invokable
.
然后我们可以像这样使用它:
We can then use it like:
template<typename F>
typename std::enable_if<invokable<double(int),F>()>::type
f(F&&){
std::cout << "can be invoked\n";
}
void f(bool) {
std::cout << "is bool\n";
}
鲍勃是你的叔叔.
真正的问题是std::function<double(int)>
的构造函数没有进行类似的测试,而是(错误地)声称可以从任何东西构造它.这是标准中的一个缺陷,我怀疑一旦概念标准化就可以解决.
The real problem is that std::function<double(int)>
's constructor does not do a similar test, and instead claims (falsely) that it can be constructed from anything at all. This is a flaw in the standard, one I suspect will be fixed once concepts are standardized.
这篇关于C ++ 11 Lambda函数隐式转换为bool vs.std :: function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!