标准库是否存在支持多输出项的transform类泛型算法?
我需要实现字符串转义功能:复制字符时,若输入包含"或\,则在输出中为其前置\。我已实现通用的transformEscapeCodeUnits模板函数,代码如下:
//! Given a range of code units (e.g., bytes in utf-8), transform them to an output range. //! If a code unit needs escaping (per the given predicate), insert esc before that code unit in the output. template <typename InRange, typename OutIter, typename NeedsEscapingPred, typename EscCodeUnit> OutIter transformEscapeCodeUnits(const InRange& in, OutIter out, NeedsEscapingPred needsEscaping, EscCodeUnit esc) { for (const auto& codeUnit : in) { if (needsEscaping(codeUnit)) { *out++ = esc; } *out++ = codeUnit; } return out; } //! Convenience overload for common case: template <typename InRange, typename OutIter> OutIter transformEscapeCodeUnits(const InRange& in, OutIter out, char esc = '\\') { return transformEscapeCodeUnits(in, out, [](auto c) { return c == '\\' || c == '"'; }, esc); }
遵循“无原始循环”原则,我查找C++标准库<algorithm>和<numeric>头文件,发现replace_if、replace_copy_if等算法均不支持将输入序列转换为更长的输出序列。我自行实现了可输出0到多个元素的transform_items泛型算法,代码如下:
//! Like transform, but TransformItem takes an element and an iterator and writes zero or more output elements: template <typename InRange, typename OutIter, typename TransformItem> OutIter transform_items(InRange&& inRange, OutIter out, TransformItem transformItem) { for (auto&& x : std::forward<InRange>(inRange)) { out = transformItem(std::forward<decltype(x)>(x), out); } return out; }
并通过该算法实现转义逻辑:transform_items(in, out, [shouldEsc, esc](auto c, auto out) { if (shouldEsc(c)) { *out++ = esc; } *out++ = c; })。请问标准库中是否存在此类算法?
C标准库(截至C23)中没有直接对应你实现的transform_items的算法。
标准库中的std::transform是严格的“一对一”转换:每个输入元素对应恰好一个输出元素,无法实现一个输入元素生成0个或多个输出元素的场景。而replace_copy_if这类算法只是替换元素,不会改变输出序列的长度,同样无法满足你的需求。
你可以借助std::for_each来模拟类似逻辑,但本质上还是需要在回调里手动处理输出迭代器的推进,和你自己实现的transform_items思路一致,并没有更简洁的标准库方案。因此,你自行实现的transform_items是合理且必要的,用来填补标准库在“一对多”序列转换场景中的空白。
内容的提问来源于stack exchange,提问作者Ben

