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

问题描述 投票:2回答:3

请考虑以下代码:

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? (那么所有可能的语法是什么,如果有几个)
c++ function parameter-passing overloading c++17
3个回答
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
投票

当编译器解析时

std::invoke(f, 3);

它没有考虑invoke的实现来确定哪个f超载是最合适的。

因此,没有其他信息,编译器无法解析f。您可以通过将f强制转换为适当的重载来提供其他信息。

std::invoke(static_cast<void(*)(int)>(f), 3);

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 );
© www.soinside.com 2019 - 2024. All rights reserved.