我正在尝试一些C ++ 17功能,并遇到了std :: invoke。然后我尝试了这段代码:
#include <iostream>
#include <functional>
void f(int i) { std::cout << "fa "; }
void f(float f) { std::cout << "fb "; }
int main() {
f(0.f);
std::invoke(f, 0.f);
}
我收到了这些错误:
main.cpp: In function 'int main()':
main.cpp:9:23: error: no matching function for call to 'invoke(<unresolved overloaded function type>, float)'
std::invoke(f, 0.f);
In file included from main.cpp:2:0:
c:/compilers/mingw/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/functional:77:5: note: candidate: template<class _Callable, class ... _Args> std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&& ...)
invoke(_Callable&& __fn, _Args&&... __args)
^~~~~~
c:/compilers/mingw/lib/gcc/x86_64-w64-mingw32/7.1.0/include/c++/functional:77:5: note: template argument deduction/substitution failed:
main.cpp:9:23: note: couldn't deduce template parameter '_Callable'
std::invoke(f, 0.f);
^
我不是cpp pro,这只是为了实验目的。我可能不会在这样的情况下使用它,但为什么它无法解决函数重载?
答案 0 :(得分:1)
您甚至可以将示例简化为:
void f(int i) {}
void f(float f) {}
template<typename F>
void foo(F) {}
foo(f); // compilation error here
编译错误的原因很简单:编译器不知道您将使用哪个f
重载。
为了避免此类错误,您应该帮助编译器使用static_cast
推导出使用显式强制转换的正确类型:
foo(static_cast<void(*)(float)>(f));
std::invoke
:
std::invoke(static_cast<void(*)(float)>(f), 0.f);
答案 1 :(得分:1)
Edgar's answer explains why this gives you an error, but there is a nicer way to work around it than having to use a cast, which requires you to provide the exact function signature (which might not be known).
It involves "lifting" the overload resolution into a templated operator()
function:
std::invoke([](auto&&... xs) -> decltype(auto) { return f(std::forward<decltype(xs)>(xs)...); }, 0.f);
Now this looks wordy, and it is, but you can make it more palatable with a macro:
#define LIFT(F) \
([](auto&&... xs) -> decltype(auto) { \
return F(::std::forward<decltype(xs)>(xs)...); \
})
std::invoke(LIFT(f), 0.f);