C++ 函数不能用作作为函子或谓词传递的类型的原因是什么?
函子的主要目的之一是充当函数,以便可以以函数方式调用它。好吧,它可以做更多的事情(有状态等),但是为什么我们不能使用函数而不是函子,因为函子的唯一目的是被调用?
好吧,应该构造对象,对于函子也是如此,但是如果我们看到函数已被传递,则可以跳过这一步。
在下面的代码中,函数和函子的行为类似,直到我尝试将它们传递给 std::map。
#include <algorithm>
#include <map>
#include <ranges>
#include <span>
#include <vector>
bool std_span_less(const std::span<const unsigned int> lhs, const std::span<const unsigned int> rhs) {
return std::ranges::lexicographical_compare(lhs, rhs);
}
struct std_span_less_fn {
bool operator() (const std::span<const unsigned int> lhs, const std::span<const unsigned int> rhs) const {
return std::ranges::lexicographical_compare(lhs, rhs);
}
};
int main()
{
using fn_type = bool (*)(const std::span<const unsigned int> , const std::span<const unsigned int> );
std::vector<unsigned int> lexems = { 0, 1, 2 };
std_span_less_fn fn_obj;
auto span1 = std::span(&(lexems[0]), 1);
auto span2 = std::span(&(lexems[0]), 2);
auto res_fn = fn_obj(span1, span2); // Can be used as function
auto res = std_span_less(span1, span2); // Naturally used as function
std::map<std::span<const unsigned int>, int, std_span_less_fn> sentences_fn;
std::map<std::span<const unsigned int>, int, std_span_less> sentences; // Doesn't compile
sentences_fn[std::span(&(lexems[0]), 1)] = 0;
sentences_fn[std::span(&(lexems[2]), 1)] = 2;
sentences_fn[std::span(&(lexems[1]), 1)] = 1;
}
Run Code Online (Sandbox Code Playgroud)
限制传递函数的唯一原因是这个对象构造还是我遗漏了其他东西?
我阅读了有关的文档,但未能找到明确的声明,除了我模糊的“函数是类型吗?”之外,std::map什么使得不可能传递函数。Compare想法。
您可以将函数作为模板参数传递,但需要将其作为指向函数的指针传递。您需要它的原因是因为函数类型正是这样,只是一种类型,您不能像使用仿函数那样从中创建对象。您可以做的是拥有一个指向函数的指针,然后可以将该指针分配给它应该指向的实际函数。这样做会改变
std::map<std::span<const unsigned int>, int, std_span_less> sentences;
Run Code Online (Sandbox Code Playgroud)
到
std::map<std::span<const unsigned int>, int, decltype(std_span_less)*> sentences{&std_span_less};
^ make a pointer type ^ ^^^^^^^^^^^^^^
|
initialize with a pointer to the function you want to use
Run Code Online (Sandbox Code Playgroud)
您也可以使用
std::integral_constant<decltype(&std_span_less), std_span_less>
Run Code Online (Sandbox Code Playgroud)
作为将函数指针值包装到类型中的比较类型,因此您不需要使用指针初始化映射。这将代码更改为:
std::map<std::span<const unsigned int>, int,
std::integral_constant<decltype(&std_span_less), std_span_less>> sentences;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |