从 std 传递函数作为函数参数的问题

问题描述 投票:0回答:1

我正在尝试弄清楚如何将

std
函数作为参数传递。这是一个简短的例子:

#include <cmath>
#include <functional>
#include <iostream>

void bar(const double v, std::function<int(int)> foo) {
  std::cout << foo(v) << std::endl;
}

int main() {
  bar(-23., std::abs);
}

此代码无法编译并显示消息没有匹配函数来调用

bar
,但如果删除
std
前缀,一切正常。怎么回事?

c++ std std-function
1个回答
5
投票

std::abs
不是一个功能。它有许多功能,它是一个重载集(参见此处https://en.cppreference.com/w/cpp/numeric/math/abs)。因此,您不能这样获取它的地址。这就是你不能像这样将它传递给其他函数的原因。即使只有一个重载,标准库中的大多数函数也无法获取其地址。只有少数例外。

接下来,当您需要将可调用对象传递给函数时,

std::function
不是要始终使用的 goto 类型。
std::function
适用于需要类型擦除的可调用对象。当你不明白它的意思时没关系,你可以暂时忘记
std::function
。当你真正需要它的时候,你就会知道它有什么用。

你可以使用lambda表达式:

template <typename F>
void bar(const double v, F&& foo) {
  std::cout << foo(v) << std::endl;
}

int main() {
  bar(-23.,[](double a){ return std::abs(a);});
}

请注意,

[](auto a) { return std::abs(a); }
也可以。它会产生一个带有模板化
operator()
的类,该类在调用时被实例化。但是,您不能对函数模板执行相同的操作。

如果想避开模板,可以使用函数指针:

using func_t = double(*)(double);
void bar(const double v, func_t foo) {
  std::cout << foo(v) << std::endl;
}

如果去掉

std
前缀,那么只有一个重载继承自C:https://en.cppreference.com/w/c/numeric/math/abs。其他的是C++添加的。请注意,当与
using namespace std;
.

结合使用时,这可能会产生特别糟糕的后果
© www.soinside.com 2019 - 2024. All rights reserved.