英文:
C++17 alternative implementation for std::transform_reduce
问题
我正在处理一个项目,该项目使用C++20标准开发,但我需要在一个旧的嵌入式Linux设备上构建它,该设备支持的最高标准是C++17(gcc 8.3.0)。在分析代码基础时,我意识到导致代码无法编译的唯一C++20功能要求是缺少std::transform_reduce
,并出现以下错误:
error: ‘transform_reduce’ is not a member of ‘std’
引用的代码部分如下:
auto addresses_string = std::transform_reduce(
localAddresses.begin(), localAddresses.end(), std::string(""),
[](const std::string& a, const std::string& b) {
return a + " | " + b;
},
[](InetAddress addr) { return addr.str(); });
但是,当我查看C++17的标准文档时,似乎已经实现了大部分std::transform_reduce
的签名。该项目是基于CMake的项目,并包含以下设置,以使用C++17标准:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
我想知道是否我做错了什么,或者是否有可能在C++17中提供了缺失功能的替代实现,或者如何在不更改程序高级行为的情况下实现相同的逻辑。
英文:
Im working on a project which was developed using c++20 standard ,but I need to build it on an old embedded linux device which the highest available standard is c++17(gcc 8.3.0). analyzing the code base, I realized the only c++20 feature requirement that forbids the code to be compiled is the lake of the std::transform_reduce
that gets the following error:
error: ‘transform_reduce’ is not a member of ‘std’
the referred part of code is:
auto addresses_string = std::transform_reduce(
localAddresses.begin(), localAddresses.end(), std::string(""),
[](const std::string& a, const std::string& b) {
return a + " | " + b;
},
[](InetAddress addr) { return addr.str(); });
but as I check the std documentations it seems the c++17 has most of the std::transform_reduce signatures implemented. this project is a CMake based project and it contains the following variables set to use the c++17 standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
I was wondering if im doing something wrong or is there an possible alternative implementation available for the missing function in c++17 or how can I implement the same logic without changing the programs high level behavior.
答案1
得分: 4
以下是翻译的内容:
一个不牺牲表达能力的解决方案涉及将您的 transform_reduce
编写为一个简单的 std::accumulate
。为此,您需要一个生成 map_reduce
运算符的实用程序:
template <class M, class R>
auto map_reduce(M&& map, R&& reduce) {
return [m = std::forward<M>(map),
r = std::forward<R>(reduce)](auto& acc, auto&& val) mutable {
return r(acc, m(std::forward<decltype(val)>(val)));
};
}
然后,您的调用可以在 C++17 中编写如下:
std::accumulate(
localAddresses.begin(), localAddresses.end(), std::string(""),
map_reduce(
[](InetAddress addr) { return addr.str(); }, // 转换器
[](const std::string& a, const std::string& b) { // 累加器
return a + " | " + b;
});
演示(使用数字转换为字符串而不是地址)。
缩减(std::accumulate
/ std::reduce
)几乎可以做任何事情,只要您弄清楚如何表达累加器。要了解兔子洞有多深,可以查看此演示。
一个更普通的解决方案是“借用” transform_reduce
的实现(例如,从这里获取),并且仅在以下情况下将其提供为头文件:
#if __cplusplus < 202002L // 使用早于 C++20 的标准
// 实现放在这里
#endif
当然,在跨平台项目中,您需要考虑语言标准和编译器的组合,因为某些库功能是按照非标准顺序实现的。
英文:
A solution that doesn't sacrifice expressiveness involves writing your transform_reduce
as a simple std::accumulate
. To do this you need a utility to generate a map_reduce
operator:
template <class M, class R>
auto map_reduce(M&& map, R&& reduce) {
return [m = std::forward<M>(map),
r = std::forward<R>(reduce)](auto& acc, auto&& val) mutable {
return r(acc, m(std::forward<decltype(val)>(val)));
};
}
your call can then be is written in C++17 as:
std::accumulate(
localAddresses.begin(), localAddresses.end(), std::string(""),
map_reduce(
[](InetAddress addr) { return addr.str(); }, // transformer
[](const std::string& a, const std::string& b) { // accumulator
return a + " | " + b;
});
<kbd>Demo</kbd> (using numbers converted to strings instead of addresses).
Reduction (std::accumulate
/ std::reduce
) can pretty much do anything if you figure out how to express your accumulator. To get a sense of how deep the rabbit hole goes, check this presentation.
A more mundane solution would be to "borrow" the implementation of transform_reduce
(say from here) and make it available in a header only if
#if __cplusplus < 202002L // Using standard older than C++20
// implementation goes here
#endif
Of course in a cross platform project, you'd have to account for the combination of language standard and compiler since some library features are implemented out of standard order.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论