【问题标题】:Call a functor with a specific function from an overload set从重载集中调用具有特定函数的函子
【发布时间】:2019-01-14 13:30:41
【问题描述】:

上下文

在与数学相关的上下文中,我想定义处理<cmath> 函数的函子。出于这个问题的目的,我们将使用std::invoke 作为我们的函子。

这是格式错误的(live demo)

std::invoke(std::sin, 0.0);

(g++-8.1) 错误:没有匹配的函数调用 'invoke(, double)'

确实,std::sin 是一个重载集,编译器缺少类型信息来选择其中一个函数。

问题

如何从重载集中命名特定函数?我们可以用什么替换 LEFTRIGHT 以使以下内容格式正确并符合预期(例如,选择 double std::sin(double))?

#include <functional>
#include <cmath>

int main()
{
    (void) std::invoke(LEFT std::sin RIGHT, 0.0);
}

如果这是不可能的,有没有办法定义一个函子,使其能够感知重载集?

【问题讨论】:

  • 它必须采用LEFTRIGHT 的样式,或者将std::sin 分配给函数指针或std::function 然后使用它来调用@987654337 @ ?
  • @user463035818 它需要在调用者站点很好。例如my_invoke&lt;double(double)&gt;(std::sin, 0) 可以。
  • @RobertAndrzejuk 这不是同一个问题:您提出的 dup 是模板扣除失败;我的问题是“如何从重载集中命名特定函数”。两者之间有重叠,但并不相同。

标签: c++ c++17 overloading overload-resolution


【解决方案1】:

我知道的最简单的方法是使用 lambda 来启用重载查找

std::invoke([](auto val){return std::sin(val);}, 0.0);

将允许您将任何值传递给 invoke,然后 lambda 主体将处理实际调用,然后将出现重载决议。

您可以使用宏从调用 invoke 中抽象出 lambda 主体

#define FUNCTORIZE(func) [](auto&&... val) noexcept(noexcept(func(std::forward<decltype(val)>(val)...))) -> decltype(auto) {return func(std::forward<decltype(val)>(val)...);}
//...
std::invoke(FUNCTORIZE(std::sin), 0.0);

【讨论】:

  • 这是我使用的,我希望有一种方法可以提供语法糖:/ 我想我们拥有的越多,我们要求的越多。糖会让人上瘾。
  • @YSC FWIW,您可以将其包装在宏中,如果您愿意,我可以将其添加到答案中。希望我们也能在下一个标准之一中获得abbreviated lambdas
  • 我不知道 :)
  • 虽然如果你要使用宏,还不如全力以赴auto&amp;&amp;...-&gt; decltype()noexcept
  • 恐怕没有缩写的 lambdas :-(
【解决方案2】:

如何从重载集中命名特定函数?

static_cast。例如

std::invoke(static_cast< double(*)(double) >( &std::sin ), 0.0);

有更简单的方法可以解决这个问题,例如使用通用 lambda 来避免那种可怕的语法:

std::invoke([](auto x){ return std::sin(x); }, 0.0);

在 Qt 中,将重载函数的地址提取到 helpers 已经被引入的地步,我们遇到了一些难题。我讨论了这种助手here 的可能实现。

static_cast 用法的规范参考是here

【讨论】:

    猜你喜欢
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 2012-11-21
    • 2019-01-08
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    相关资源
    最近更新 更多