请考虑以下代码:
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
? (那么所有可能的语法是什么,如果有几个)最好的方法是手动创建重载集。
#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
作为期望/预期调用。
请注意,这并不完全等同于直接传递预期函数(值得注意的例外包括按值取值不可移动类型的对象的函数),但如果没有明确的手动类型选择,它是最好的。
当编译器解析时
std::invoke(f, 3);
它没有考虑invoke
的实现来确定哪个f
超载是最合适的。
因此,没有其他信息,编译器无法解析f
。您可以通过将f
强制转换为适当的重载来提供其他信息。
std::invoke(static_cast<void(*)(int)>(f), 3);
您可以只显式指定第一个模板参数。
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 );