为何std::is_invocable返回false但std::invoke可正常调用?
为啥明明能调用的函数,
is_invocable_v却判定不可调用? 这个问题乍一看确实有点矛盾,但其实是没搞清楚std::is_invocable_v的检查逻辑和decltype的细节,咱们慢慢捋:
先搞懂两个decltype的结果
decltype(foo)得到的是函数类型void(int&),这个没问题,foo确实接受一个int的非const左值引用。decltype(a)得到的是**int类型**,注意哦,这里是变量的基础类型,不是a这个左值本身的类型。
std::is_invocable_v到底在检查啥?
std::is_invocable_v<F, Args...>的核心规则是:判断能不能用**Args类型的右值**作为参数,调用F类型的可调用对象。
放到你的代码里,它检查的是:能不能拿一个int右值(比如直接传5)去调用void(int&)?答案肯定是不行——C++不允许把非const左值引用绑定到右值。这就是为啥is_invocable_v返回0的原因。
那实际调用为啥能成功?
- 直接调用
foo(a)时,a是一个int左值,完全符合int&参数的要求,自然能调用成功。 std::invoke(foo, a)的时候,std::invoke会尊重参数的实际值类别:它把左值a传递给foo的引用参数,相当于直接绑定左值,所以也能正常调用。
怎么让is_invocable_v返回正确结果?
如果你想让is_invocable_v反映实际调用的情况,得把参数类型指定为左值引用,这时候用decltype((a))(注意双层括号)就行——decltype((a))会返回int&,代表a作为左值的类型:
std::cout << std::is_invocable_v<decltype(foo), decltype((a))> << std::endl;
这样输出就会是1,和实际调用的结果一致了。
内容的提问来源于stack exchange,提问作者Baruch
相关产品推荐
相关产品推荐

