传递一个免费的函数来调用?

时间:2017-12-26 21:47:55

标签: c++ function parameter-passing overloading c++17

请考虑以下代码:

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? (如果有几个,那么所有可能的语法是什么)

3 个答案:

答案 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 );