[英]Get a view to all T's in std::vector<std::tuple<Ts…>>
Imagine I have a container which is similar to std::vector<std::tuple<Ts...>>
. 想象一下,我有一个类似于
std::vector<std::tuple<Ts...>>
的容器。
From that, I would like to get a " view
" (non-copying) to all T
's such that I can operate on that view as if it would be a standard-like container. 从那以后,我想对所有
T
进行“ view
”(非复制),这样我就可以对该视图进行操作,就好像它是一个类似标准的容器一样 。
So what I would like to have: 那么我想要的是:
using tuple_vector = std::vector<std::tuple<int,float,double>>;
tuple_vector tuple_vec = {{1, 4.f, 8.},
{2, 5.f, 9.},
{3, 6.f, 10.},
{4, 7.f, 11.}}
auto int_view = view<int>(tuple_vec);
^^^
type should be some kind of non-owning reference
// what I would like to do
int_view[0] = 10; // modify
assert(int_view[0] == std::get<int>(tuple_vec[0])); // modification should modify tuple_vec as well
I have tried std::transform
, but then I am getting a owning copy of all int
's. 我尝试过
std::transform
,但后来我得到了所有int
的拥有副本 。
std::vector<int> int_vec(tuple_vec.size());
std::transform(tuple_vec.begin(), tuple_vec.end(), int_vec.begin(), [&](const auto& elem) {
return std::get<int>(elem);
});
I am not sure if this is possible at all, but if so, I would appreciate any hints or directions. 我不确定这是否可行,但如果是这样,我会很感激任何提示或方向。
Well, if you using Eric Niebler's ranges-v3 library (which is in the process of getting adopted into the standard - there's now a Ranges TS ), you can apply your intuition to use something like std::transform
, but with a view: 好吧,如果你使用Eric Niebler的range-v3库 (它正在被采用到标准中 - 现在有一个Ranges TS ),你可以运用你的直觉来使用类似
std::transform
东西,但是有一个视图:
#include <range/v3/view/transform.hpp>
// ... etc. ...
auto int_view = tuple_vector | ranges::view::transform(
[](auto& t)->auto&{ return std::get<int>(t);} );
See this in action (Coliru), with modification of one of the elements even. 看到这个在行动 (Coliru),甚至修改了其中一个元素。
Note: This view becomes un-modifiable if we remove the -> decltype(auto)
; 注意:如果我们删除
-> decltype(auto)
,则此视图将无法修改; the change is due to @deduplicator's answer to this question . 这个变化是由于@ deduplicator对这个问题的回答。
You could create a vector of std::reference_wrapper
: 你可以创建一个
std::reference_wrapper
的向量:
template <typename T, typename ContainerOfTuples>
auto make_refs_to(ContainerOfTuples& tuples) {
using RefType = std::reference_wrapper<T>;
std::vector<RefType> refs;
refs.reserve(std::size(tuples));
std::transform(std::begin(tuples), std::end(tuples), std::back_inserter(refs),
[](auto& tup) -> RefType { return {std::get<T>(tup)}; });
return refs;
}
auto double_view = make_refs_to<double>(tuple_vec);
double_view[1].get() += 3.14; // Caveat: must access through .get().
Going further... here's how we can get references to many types: 更进一步......这是我们如何获得许多类型的引用:
namespace detail {
// When many types are asked for, return a tuple of references.
template <typename... T> struct RefTypeImpl {
using type = std::tuple<std::reference_wrapper<T>...>;
};
// When a single type is asked for, return a single reference.
template <typename T> struct RefTypeImpl<T> {
using type = std::reference_wrapper<T>;
};
// When two types are asked for, return a pair for more convenient access.
template <typename T, typename U> struct RefTypeImpl<T, U> {
using type = std::pair<std::reference_wrapper<T>, std::reference_wrapper<U>>;
};
} // namespace detail
template <typename... Ts, typename ContainerOfTuples>
auto make_refs_to(ContainerOfTuples& tuples) {
using RefType = typename detail::RefTypeImpl<Ts...>::type;
std::vector<RefType> refs;
refs.reserve(std::size(tuples));
std::transform(std::begin(tuples), std::end(tuples), std::back_inserter(refs),
[](auto& tup) -> RefType { return {std::get<Ts>(tup)...}; });
return refs;
}
auto int_float_view = make_refs_to<int, float>(tuple_vec);
std::cout << (int_float_view[2].first.get() == 3) << '\n';
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.