请考虑以下代码:
class _c {
public:
_c(int);
_c(function<void(void)>);
};
分别为int
和function<void(void)>
定义了两个构造函数的类。
这意味着我现在可以像这样实例化这些类的对象:
_c a = _c(0);
_c b = _c([]() {});
现在,我声明一个以_c
对象作为参数的函数:
void _f(_c __c) {};
现在我可以用我的_c
对象调用此函数,如下所示:
_f(_c(0));
_f(_c([]() {}));
直到这里,一切看起来都不错。现在,如果我试图在没有明确调用_f
构造函数的情况下调用我的_c
函数,我会看到:
_f(0) // works because C++ knows to construct a _c with an 0 by using _c(int)
但是,
_f([]() {}) // fails with 'no matching function for call to _f'
我不明白为什么会发生这种情况,有人可以解释为什么在使用<functional>
类型时它不起作用吗?
此外,我正在编译:Apple LLVM 6.0版(clang-600.0.57)(基于LLVM 3.5svn)
答案 0 :(得分:3)
当您致电f(0)
时,参数类型为int
,可转换为_c
。这是通常的一步转换。
但是,当您调用_f([]() {})
时,参数是lambda类型(由编译器生成),而不是类型std::function<void(void)>
。所以在这种情况下,需要 两次转换 - 一次从lambda类型到std::function<void(void)>
,再到_c
(使用转换构造函数)
语言允许两步转换不,这就是您的代码不起作用的原因。
解决方案是添加模板化构造函数:
template<typename Functor, typename =decltype(std::declval<Functor&>()())>
_c(Functor && func);
然后你的代码应该可以工作。