C++是一个不断发展的目标,包括迭代器(c++20有相关概念)。但是,如果有一种懒惰的解决方案岂不是更好?即在不进行转换(参见其他答案)和编写循环以将
vector<double>
转换为
vector<tuple<double,double>>
的情况下,动态生成元组。
现在我觉得需要免责声明,因为我不确定这是否完全正确(语言专家会指出是否有遗漏)。但它可以编译并产生预期的输出。这很不错,对吧?是的。
这个想法是构建一个伪容器(实际上只是底层容器的外观),具有自己的迭代器,在运行时动态生成所需的输出类型。
#include <vector>
#include <tuple>
#include <iostream>
#include <iterator>
template <class SourceIter>
struct PairWise {
PairWise() = delete;
PairWise(SourceIter first, SourceIter last)
: first{first}
, last{last}
{
}
using value_type =
typename std::tuple<
typename SourceIter::value_type,
typename SourceIter::value_type
>;
using source_iter = SourceIter;
struct IterState {
PairWise::source_iter first;
PairWise::source_iter last;
PairWise::source_iter current;
IterState(PairWise::source_iter first, PairWise::source_iter last)
: first{first}
, last{last}
, current{first}
{
}
friend bool operator==(const IterState& a, const IterState& b) {
return (a.first == b.first)
&& (a.last == b.last)
&& (a.current == b.current);
}
IterState& operator++() {
if (std::distance(current,last) >= 2) {
current++;
current++;
}
return *this;
}
const PairWise::value_type operator*() const {
return std::make_tuple(*current, *(current+1));
}
};
using iterator = IterState;
using const_iterator = const IterState;
const_iterator cbegin() const {
return IterState{first,last};
}
const_iterator cend() const {
auto i = IterState{first,last};
i.current = last;
return i;
}
const_iterator begin() const {
return IterState{first,last};
}
const_iterator end() const {
auto i = IterState{first,last};
i.current = last;
return i;
}
source_iter first;
source_iter last;
};
std::ostream& operator<<(std::ostream& os, const std::tuple<double,double>& value) {
auto [a,b] = value;
os << "<" << a << "," << b << ">";
return os;
}
template <class Container>
auto pairwise( const Container& container)
-> PairWise<typename Container::const_iterator>
{
return PairWise(container.cbegin(), container.cend());
}
int main( int argc, const char* argv[]) {
using VecF64_t = std::vector<double>;
VecF64_t data{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
for (const auto x : pairwise(data)) {
std::cout << x << std::endl;
}
return 0;
}