英文:
In C++ and range-v3, how to first transform a view and then convert it to a map?
问题
如何将任何范围作为输入,首先将其元素转换为元组,然后保存在std::map
中,使用ranges::to
?
这段代码有效,创建了一个元组的向量:
#include <range/v3/all.hpp>
#include <fmt/format.h>
#include <fmt/ranges.h>
int main() {
auto v = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_tuple(v, v*2); })
| ranges::to<std::vector>();
fmt::print("{}\n", v);
}
将vector
替换为map
,我期望得到一个映射(其中元组的第一个元素变为键,第二个元素变为它们的值),但是代码无法编译:
#include <range/v3/all.hpp>
#include <fmt/format.h>
#include <fmt/ranges.h>
int main() {
auto v = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_tuple(v, v*2); })
| ranges::to<std::map>();
fmt::print("{}\n", v);
}
我得到以下错误消息:
test.cpp:11:10: error: invalid operands to binary expression ('invoke_result_t<ranges::views::transform_base_fn, ranges::iota_view<int, int>, (lambda at test.cpp:9:30)>' (aka 'transform_view<ranges::iota_view<int, int>, (lambda at test.cpp:9:30)>' and 'detail::to_container_fn<detail::from_range<std::map>>' (aka 'closure<ranges::detail::from_range<std::map>, ranges::detail::to_container::fn<ranges::detail::from_range<std::map>>>)
注:我在互联网上没有找到很多使用ranges::to<map>
的示例,但在这个答案中:https://stackoverflow.com/a/74433668 中有一个有效的代码,将ranges::views::zip
的结果转换为映射。由于zip
生成"类似元组"的元素,我期望我的代码也能工作,但显然并不那么简单。
编译器是Clang++版本15.0.6,ranges是当前的主分支。
英文:
Having any range as an input, how to first convert its elements to tuples and then save them in a std::map
with ranges::to
?
This code works and creates a vector of tuples:
#include <range/v3/all.hpp>
#include <fmt/format.h>
#include <fmt/ranges.h>
int main() {
auto v = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_tuple(v, v*2); })
| ranges::to<std::vector>();
fmt::print("{}\n", v);
}
Replacing vector
by map
, I'd expect to receive a map instead (with first elements of the tuples becoming keys and second elements becoming their values), but the code doesn't compile:
#include <range/v3/all.hpp>
#include <fmt/format.h>
#include <fmt/ranges.h>
int main() {
auto v = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_tuple(v, v*2); })
| ranges::to<std::map>();
fmt::print("{}\n", v);
}
I get:
test.cpp:11:10: error: invalid operands to binary expression ('invoke_result_t<ranges::views::transform_base_fn, ranges::iota_view<int, int>, (lambda at test.cpp:9:30)>' (aka 'transform_view<ranges::iota_view<int, int>, (lambda at test.cpp:9:30)>') and 'detail::to_container_fn<detail::from_range<std::map>>' (aka 'closure<ranges::detail::from_range<std::map>, ranges::detail::to_container::fn<ranges::detail::from_range<std::map>>>'))
Notes: I didn't find many examples of using ranges::to<map>
in the internet, but in this answer: https://stackoverflow.com/a/74433668 there's working code where the result of ranges::views::zip
is converted to a map. Since zip
produces "tuple-like" elements, I expected my code to work too, but apparently it's not that straightforward.
Compiler is Clang++ v. 15.0.6, ranges is current master.
答案1
得分: 1
你需要一个std::pair
,而不是std::tuple
(示例链接):
auto m = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_pair(v, v*2); })
| ranges::to<std::map>;
总之,像这样是可以的:
std::vector<std::pair<int, int>> v;
std::map<int, int> M(v.begin(), v.end());
但像这样是不可以的:
std::vector<std::tuple<int, int>> v;
std::map<int, int> M(v.begin(), v.end());
或者,更简单地,如评论中建议的:
std::map<int, int> P{{std::pair<int, int>{}}}; // 可行
std::map<int, int> T{{std::tuple<int, int>{}}}; // 错误
英文:
You need a std::pair
, not a std::tuple
(working example):
auto m = ranges::views::iota(3, 10)
| ranges::views::transform([](auto const &v){ return std::make_pair(v, v*2); })
| ranges::to<std::map>;
After all, while something like this is fine,
std::vector<std::pair<int, int>> v;
std::map<int,int> M(v.begin(), v.end());
something like this is not
std::vector<std::tuple<int, int>> v;
std::map<int,int> M(v.begin(), v.end());
Or, more simply as suggested in a comment,
std::map<int,int> P{{std::pair<int, int>{}}}; // OK
std::map<int,int> T{{std::tuple<int, int>{}}}; // Error
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论