std::transform() 算法
- 自 C++20 起
- 自 C++17 起
- C++17 之前
// (1)
template< class InputIt, class OutputIt, class UnaryOperation >
constexpr OutputIt transform( InputIt first1, InputIt last1,
OutputIt d_first, UnaryOperation unary_op );
// (2)
template< class InputIt1, class InputIt2,
class OutputIt, class BinaryOperation >
constexpr OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );
// (3)
template< class ExecutionPolicy, class ForwardIt1,
class ForwardIt2, class UnaryOperation >
ForwardIt2 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 d_first, UnaryOperation unary_op );
// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class BinaryOperation >
ForwardIt3 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
ForwardIt3 d_first, BinaryOperation binary_op );
// (1)
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1,
OutputIt d_first, UnaryOperation unary_op );
// (2)
template< class InputIt1, class InputIt2,
class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );
// (3)
template< class ExecutionPolicy, class ForwardIt1,
class ForwardIt2, class UnaryOperation >
ForwardIt2 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 d_first, UnaryOperation unary_op );
// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class BinaryOperation >
ForwardIt3 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
ForwardIt3 d_first, BinaryOperation binary_op );
// (1)
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1,
OutputIt d_first, UnaryOperation unary_op );
// (2)
template< class InputIt1, class InputIt2,
class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );
将给定函数应用于某个范围,并将结果存储在另一个范围中,保持原始元素顺序并从 d_first
开始。
-
(1) 一元操作
unary_op
应用于由 [ first1; last1 ) 定义的范围。 -
(2) 二元操作
binary_op
应用于两个范围的元素对- 一个由 [
first1
;last1
) 定义 - 另一个从
first2
开始。
- 一个由 [
-
(3, 4) 与 (1) 和 (2) 相同,但根据策略执行。
重载决议这些重载只有在
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>
为true
时才参与重载决议。 (直到 C++20)std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>
为true
时才参与重载决议。 (自 C++20 起)
unary_op
和 binary_op
不得使任何迭代器(包括尾迭代器)失效,或修改所涉及范围的任何元素。
参数
first1 last | 要转换的第一个元素范围。 |
first2 | 要转换的第二个元素范围的开头。 |
d_first | 目标范围的开头,可能等于 |
policy | 要使用的执行策略。有关详细信息,请参见执行策略。 |
unary_op | 将要应用的一元操作函数对象。 函数的签名应与以下内容等效
|
unary_op | 将要应用的二元操作函数对象。 函数的签名应与以下内容等效
|
类型要求
InputIt InputIt1 InputIt2 | LegacyInputIterator |
OutputIt | LegacyOutputIterator |
ForwardIt1 ForwardIt2 ForwardIt3 | LegacyForwardIterator |
返回值
指向已转换的最后一个元素之后的元素的输出迭代器。
复杂度
- (1, 3)
unary_op
的应用次数恰好为std::distance(first1, last1)
。 - (2, 4)
unary_op
的应用次数恰好为std::distance(first1, last1)
。
异常
带有模板参数 ExecutionPolicy
的重载报告错误如下
- 如果作为算法一部分调用的函数执行时抛出异常,并且
ExecutionPolicy
是标准策略之一,则调用std::terminate
。对于任何其他ExecutionPolicy
,行为是实现定义的. - 如果算法未能分配内存,则抛出
std::bad_alloc
。
可能的实现
transform (1)
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op )
{
while (first1 != last1)
*d_first++ = unary_op(*first1++);
return d_first;
}
transform (2)
template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform(InputIt1 first1, InputIt1 last1,
InputIt2 first2, OutputIt d_first,
BinaryOperation binary_op)
{
while (first1 != last1)
*d_first++ = binary_op(*first1++, *first2++);
return d_first;
}
备注
std::transform
不保证按顺序应用 unary_op
或 binary_op
。
若要按顺序将函数应用于序列或应用修改序列元素的函数,请使用 std::for_each
。
示例
以下代码使用 transform
通过 std::toupper
函数将字符串就地转换为大写,然后将每个字符转换为其序数值。
然后,使用带有投影的 transform
将 std::vector<Foo>
的元素转换为字符以填充 std::string
。
以下代码使用 transform 通过 std::toupper
函数将字符串就地转换为大写,然后将每个字符转换为其序数值
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
void print_ordinals(std::vector<std::size_t> const& ordinals)
{
std::cout << "ordinals: ";
for (std::size_t ord : ordinals)
std::cout << std::setw(3) << ord << ' ';
std::cout << '\n';
}
int main()
{
std::string s {"hello"};
std::transform(s.cbegin(), s.cend(),
s.begin(), // write to the same location
[](unsigned char c) { return std::toupper(c); });
std::cout << "s = " << std::quoted(s) << '\n';
// achieving the same with std::for_each (see Notes above)
std::string g {"hello"};
std::for_each(g.begin(), g.end(), [](char& c) // modify in-place
{
c = std::toupper(static_cast<unsigned char>(c));
});
std::cout << "g = " << std::quoted(g) << '\n';
std::vector<std::size_t> ordinals;
std::transform(s.cbegin(), s.cend(), std::back_inserter(ordinals),
[](unsigned char c) { return c; });
print_ordinals(ordinals);
std::transform(ordinals.cbegin(), ordinals.cend(), ordinals.cbegin(),
ordinals.begin(), std::plus<>{});
print_ordinals(ordinals);
}
s = "HELLO"
g = "HELLO"
ordinals: 72 69 76 76 79
ordinals: 144 138 152 152 158