请考虑以下代码:
void f(int) {std::cout << "void f(int)" << std::endl;}
void f(double) {std::cout << "void f(double)" << std::endl;}
void f(int*) {std::cout << "void f(int*)" << std::endl;}
std::invoke(f, 3);
我有两个问题:
f
的整个重载集并让invoke
选择正确的函数? (没有任何帮助类,这是一个纯语言问题)void f(int)
传递给invoke
? (如果有几个,那么所有可能的语法是什么)答案 0 :(得分:4)
最好的方法是手动创建重载集。
#define OVERLOADS_OF(name) [&](auto&&... args) -> decltype(name(FWD(args)...)) noexcept(noexcept(name(FWD(args)...))) { return name(FWD(args)...); }
然后将其传递给:
invoke(OVERLOADS_OF(f), 3)
这样,编译器仍在为我们执行重载解析 - 我们不必自己执行此操作 - 并且根据需要/期望调用int
的重载。
请注意,这并不完全等同于直接传递预期函数(值得注意的例外包括按值取值不可移动类型的对象的函数),但如果没有明确的手动类型选择,这是最好的。
答案 1 :(得分:1)
当编译器解析
时std::invoke(f, 3);
它不会查看invoke
的实现,以确定f
的哪个重载是最合适的。
因此,如果没有其他信息,编译器无法解析f
。您可以通过将f
强制转换为适当的重载来提供其他信息。
std::invoke(static_cast<void(*)(int)>(f), 3);
答案 2 :(得分:0)
您可以明确指定第一个模板参数。
std::invoke<void( int )>(f, 3);
这是一个示范程序。
#include <iostream>
#include <functional>
void f(int) {std::cout << "void f(int)" << std::endl;}
void f(double) {std::cout << "void f(double)" << std::endl;}
void f(int*) {std::cout << "void f(int*)" << std::endl;}
int main()
{
std::invoke<void( int )>(f, 3);
std::invoke<void( double )>(f, 3);
std::invoke<void( int * )>(f, nullptr);
return 0;
}
它的输出是
void f(int)
void f(double)
void f(int*)
另一种方法是使用中间指针。例如
void ( *pf )( int ) = f;
std::invoke( pf, 3 );