Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;-迭代双元组的向量 我有一个双倍的C++向量,保证有偶数个元素。该向量将一组点的坐标存储为x,y坐标:_C++_Vector_Stl_Iterator_C++17 - Fatal编程技术网

C++;-迭代双元组的向量 我有一个双倍的C++向量,保证有偶数个元素。该向量将一组点的坐标存储为x,y坐标:

C++;-迭代双元组的向量 我有一个双倍的C++向量,保证有偶数个元素。该向量将一组点的坐标存储为x,y坐标:,c++,vector,stl,iterator,c++17,C++,Vector,Stl,Iterator,C++17,A[2*i]是第i点的x坐标 [2*i+1]是第i点的y坐标 如何实现一个允许我使用STL风格算法的迭代器(一个采用迭代器范围的算法,其中对迭代器的解引用返回对应点的x,y坐标对应的一对双精度) 如果有帮助的话,我使用的是C++17。没有一种简单的“C++”方法可以做到干净并避免复制原始数组。总是有这样的(复制): 向量中的元素存储在连续的内存区域中,所以您可以使用简单的指针算术来访问一对双精度 迭代器的operator++应该在每次使用时跳过2倍 operator*可以将引用的元组返回到双值,

A[2*i]是第i点的x坐标

[2*i+1]是第i点的y坐标

如何实现一个允许我使用STL风格算法的迭代器(一个采用迭代器范围的算法,其中对迭代器的解引用返回对应点的x,y坐标对应的一对双精度)

如果有帮助的话,我使用的是C++17。

没有一种简单的“C++”方法可以做到干净并避免复制原始数组。总是有这样的(复制):


向量中的元素存储在连续的内存区域中,所以您可以使用简单的指针算术来访问一对双精度

迭代器的
operator++
应该在每次使用时跳过2倍

operator*
可以将引用的元组返回到双值,因此您可以读取(
pair=*it
)或编辑值(
*it=pair

struct Cont{
std::vector&v;
Cont(std::vector&v):v(v){}
结构迭代器:公共std::迭代器{
double*ptrData=nullptr;
迭代器(双*数据):ptrData(数据){}
迭代器和运算符++(){ptrData+=2;返回*this;}
迭代器运算符++(int){Iterator copy(*this);ptrData+=2;返回copy;}
自动运算符*(){return std::tie(*ptrData,*(ptrData+1));}
布尔运算符!=(常量迭代器和其他)常量{return ptrData!=other.ptrData;}
};
自动开始(){返回迭代器(v.data());}
自动结束(){返回迭代器(v.data()+v.size());}
};
int main(){
std::向量v;
v、 调整大小(4);
续c(v);
for(auto it=c.begin();it!=c.end();it++){
*it=std::tuple(20,30);
}

std::cout如果你能保证std::vector总是有偶数个条目,你可以利用这样一个事实,即一个双精度向量将与一个双精度向量具有相同的内存布局。这是一种肮脏的把戏,但如果你能避免的话,我不建议你这样做。好消息是,标准保证向量元素将是连续的

inline const std::vector<std::pair<double, double>>& make_dbl_pair(std::vector<double>& v)
{
  return reinterpret_cast<std::vector<std::pair<double, double>>&>(v);
}
inline const std::vector和make_dbl_对(std::vector&v)
{
返回重新解释(v);
}
这只适用于使用迭代器的迭代。该大小可能是向量中对数的两倍,因为它下面仍然是一个双精度向量

例如:

int main(int argc, char* argv[])
{
  std::vector<double> dbl_vec = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 };
  const std::vector<std::pair<double, double>>& pair_vec = make_dbl_pair(dbl_vec);
  for (auto it = pair_vec.begin(); it != pair_vec.end(); ++it) {
    std::cout << it->first << ", " << it->second << "\n";
  }
  std::cout << "Size: " << dbl_vec.size() << "\n";
  return 0;
}
intmain(intargc,char*argv[])
{
向量dbl_vec={0.0,1.1,2.2,3.3,4.4,5};
const std::vector&pair_vec=make_dbl_pair(dbl_vec);
对于(自动it=pair_vec.begin();it!=pair_vec.end();+it){

std::cout firstC++是一个移动的目标——当涉及到迭代器时也是如此(C++20有这方面的概念…)。但是如果有一个懒惰的解决方案来解决这个问题会不会很好。例如,元组是动态生成的,而不是强制转换(参见其他答案)无需编写循环即可将
向量
转换为
向量

现在我觉得我需要一个免责声明,因为我不确定这是否完全正确(如果我遗漏了什么,语言律师希望会指出)。但它编译并生成预期的输出。这是什么,是吗?!是的

其思想是使用自己的迭代器构建一个伪容器(实际上只是底层容器的一个门面),动态生成所需的输出类型

#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) {
      // std::cout << "operator==(a,b)" << std::endl;
      return (a.first == b.first) 
        && (a.last == b.last)
        && (a.current == b.current);
    }
    IterState& operator++() {
      // std::cout << "operator++()" << std::endl;
      if (std::distance(current,last) >= 2) {
        current++;
        current++;
      }
      return *this;
    }
    const PairWise::value_type operator*() const {
      // std::cout << "operator*()" << std::endl;
      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 {
    // std::cout << "begin()" << std::endl;
    return IterState{first,last};
  }
  const_iterator end() const {
    // std::cout << "end()" << std::endl;
    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;
}

#包括
#包括
#包括
#包括
模板
结构成对{
成对()=删除;
成对(先源iter,后源iter)
:first{first}
,last{last}
{
}
使用值\u类型=
typename std::tuple<
typename SourceIter::value\u type,
typename SourceIter::value\u类型
>; 
使用source_iter=SourceIter;
结构IterState{
两两:源代码优先;
成对::最后一个源代码;
成对:源电流;
IterState(成对::源国际热核试验堆优先,成对::源国际热核试验堆最后)
:first{first}
,last{last}
,当前{first}
{
}
friend布尔运算符==(常量IterState&a、常量IterState&b){

//std::cout我们可以使用range-v3,带有两个适配器:

  • chunk(n)
    获取一个范围,并将其调整为大小不重叠的范围
    n
  • transform(f)
    获取
    x的范围
    并将其调整为
    f(x)
把这些放在一起,我们可以创建一个适配器,它接受一个范围并产生一个非重叠对的范围:

auto-into_pairs=rv::chunk(2)
|rv::transform([](auto&&r){return std::pair(r[0],r[1]);});
使用
r[0]
语法假定输入范围是随机访问的,在本例中,这是很好的,因为我们知道我们希望在
向量上使用它,但也可以将其推广到仅适用于前向范围,而代价是多一些语法:

| rv::transform([](自动和&r){
自动it=范围::开始(r);
自动下一步=范围::下一步(it);
返回std::pair(*it,*next);
})
,使用
fmt
方便打印:

intmain(){
向量v={1,1,2,2,3,3,4,4,5,5};
自动插入\u pairs=rv::chunk(2)
|rv::transform([](auto&&r){return std::pair(r[0],r[1]);});
//印刷品{(1,1)、(2,2)、(3,3)、(4,4)、(5,5)}
fmt::打印(“{}\n”,v|为_对);
}


问题中不清楚您想要的是
pair
s还是
pair
s。后者可以通过向
std::pair
提供显式类型,而不是依赖于类模板参数推断来实现。

我假设您正在寻找一个“懒惰的”这样,不用复制/重新格式化就可以了,对吗?正确-我假设任何人
inline const std::vector<std::pair<double, double>>& make_dbl_pair(std::vector<double>& v)
{
  return reinterpret_cast<std::vector<std::pair<double, double>>&>(v);
}
int main(int argc, char* argv[])
{
  std::vector<double> dbl_vec = { 0.0, 1.1, 2.2, 3.3, 4.4, 5.5 };
  const std::vector<std::pair<double, double>>& pair_vec = make_dbl_pair(dbl_vec);
  for (auto it = pair_vec.begin(); it != pair_vec.end(); ++it) {
    std::cout << it->first << ", " << it->second << "\n";
  }
  std::cout << "Size: " << dbl_vec.size() << "\n";
  return 0;
}
#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) {
      // std::cout << "operator==(a,b)" << std::endl;
      return (a.first == b.first) 
        && (a.last == b.last)
        && (a.current == b.current);
    }
    IterState& operator++() {
      // std::cout << "operator++()" << std::endl;
      if (std::distance(current,last) >= 2) {
        current++;
        current++;
      }
      return *this;
    }
    const PairWise::value_type operator*() const {
      // std::cout << "operator*()" << std::endl;
      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 {
    // std::cout << "begin()" << std::endl;
    return IterState{first,last};
  }
  const_iterator end() const {
    // std::cout << "end()" << std::endl;
    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;
}