c++ - 为什么 std::invoke 不处理函数重载

标签 c++

我正在试验一些 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 专家,这只是为了实验目的。我可能永远不会在这种情况下使用它,但为什么它无法解决函数重载问题?

最佳答案

Edgar 的回答解释了为什么这会给您带来错误,但是有一种比强制转换更好的解决方法,强制转换要求您提供确切的函数签名(可能不知道)。

它涉及将重载解析“提升”到模板化的 operator() 函数中:

std::invoke([](auto&&... xs) -> decltype(auto) { return f(std::forward<decltype(xs)>(xs)...); }, 0.f);

现在这看起来很罗嗦,确实如此,但是您可以使用宏使其更容易接受:

#define LIFT(F) \
    ([](auto&&... xs) -> decltype(auto) { \
        return F(::std::forward<decltype(xs)>(xs)...); \
    })

std::invoke(LIFT(f), 0.f);

关于c++ - 为什么 std::invoke 不处理函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45505017/

相关文章:

c++ - 当 C++11 应用程序使用非 C++11 库时返回值损坏

c++ - 如何使用 D2D 和类 CD2DEllipse 在 C++ MFC 上绘制椭圆

c++ - 在构造函数主体中使用初始化列表中的字段

c# - 在从 C# 调用的 DLL 中使用 std::cout

c++ - 有人可以确认这是否是单例的线程安全实现吗

c++ - 在外部测试环境时程序崩溃 - C++

c++ - 将 C++ 程序移动到前台

c++ - 在 C++ 中使用类似 C 的初始化或构造函数初始化更好吗?

c++ - Visual Studio 2005 中的默认字符集 'Unicode'

c++ - "enum - invalid conversion from int"在类里面