c++ - 带有重载转换函数的 std::transform
问题描述
我想char
从一个容器中转换所有类型的对象(例如,类型)c
并将结果(类型foo
)存储在不同的容器中v
。所需的转换函数是一个重载函数——调用它to_foo
。
考虑以下示例:
#include <algorithm>
#include <vector>
struct foo {};
foo to_foo(char) { return {}; }
foo to_foo(int) { return {}; }
int main()
{
std::array<char, 1> c;
std::vector<foo> v(c.size());
// cannot determine which instance of overloaded function "to_foo" is intended:
std::transform(c.begin(), c.end(), v.begin(), to_foo);
// ok:
std::transform(c.begin(), c.end(), v.begin(), [](auto const& ch) { return to_foo(ch); });
}
虽然在第一次转换中编译器不知道它应该采用哪个重载to_foo
(另一方面,他不能从value_type
迭代器中推断出它吗?),但我不明白他为什么是能够在第二次转换中这样做。这里发生了什么事?
解决方案
您必须通过强制转换明确告诉它要使用哪个重载to_foo
:
std::transform(c.begin(), c.end(), v.begin(), static_cast<foo (*)(char)>(to_foo));
一元操作参数的类型是与std::transform
用于迭代器的模板参数不同的模板参数。所以它必须使用你传递的值的类型来推断模板参数。to_foo
的类型不明确,因此无法完成该过程。将函数指针转换为特定的重载类型使其明确。
在第二种形式中,lambda 是一个可调用对象,使用auto
使对象的()
运算符成为函数模板:
struct NamelessGenericLambda {
template <typename T>
foo operator ()(T const& ch) { return to_foo(ch); }
};
std::transform(c.begin(), c.end(), v.begin(), NamelessGenericLambda{});
类型很明确,因此可以实例化std::transform
模板。
然后std::transform
它内部的某个地方会尝试operator ()
通过传递一个char
. 因为它传递了一个明确的类型,所以编译器推断ch
是一个字符。然后它选择to_foo
使用常规重载决议的正确重载。
推荐阅读
- c++ - 对整个数组进行冒泡排序
- php - if..else 嵌套在 oci 和 php 的 while 循环中,但 if...else 没有被调用
- openlayers - 有没有办法在 openlayers 5 中强制重新加载/刷新地图?
- python - Entrez (biopython):如何将术语搜索限制在特定期刊?(考研)
- android - 由于权限政策,我无法发布我的应用
- twitter-bootstrap - Bootstrap 4 - col-sm-12 的 col 没有响应
- java - Thymeleaf 使用 th:each 动态创建表单
- java - 从 csv 文件导入 Excel 进行转换
- javascript - HTML onClick 属性不调用函数
- bash - 查找命令失败,出现“没有这样的文件或目录”错误