首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >数组,其第一个元素是任意索引的-写入容器包装器。

数组,其第一个元素是任意索引的-写入容器包装器。
EN

Code Review用户
提问于 2016-11-18 00:11:41
回答 1查看 70关注 0票数 2

问题:

在C++数组和SequenceContainers http://en.cppreference.com/w/cpp/concept/SequenceContainer (std::arraystd::dequestd::vector)中,必然是零索引的.但是,从语义的角度来看,数组的元素可以被分配给完全其他范围的索引。一个常见的例子是需要在0索引容器中存储一个1索引数组。(不过,我记得必须对任意索引的数组进行操作)

解决上述问题的办法包括:

  • 每次索引这样的数组时,记住用给定的常量倾斜索引--这会导致大量类似于vec[n-1]之类的代码--但是这种方法繁琐且容易出错(很容易忘记这个-1,而是键入vec[n],oops);
  • 为这样一个数组定义一个类,该数组具有类似于some_type &operator [] (unsigned n) {return m_arr[n-1];}的方法--但这通常是非常过分的;
  • 粗糙的方法:忘记数组是0索引的事实;把它们当作1索引,永远不要使用索引0。然而,这种方法很粗糙,对于任意索引的数组,它将失败.

建议的解决方案:

我想我应该为SequenceContainers编写一个包装器,它与标准容器的不同之处在于,它的operator[]at函数将使它们的参数偏离给定的偏移量。我编写了这个包装器的两个版本:一个是确定编译时作为模板参数,另一个是可以修改运行时。我认为两者都是必要的。

用法很简单,如计算Collatz序列前100个初始值的长度的一个简单示例所示:( https://en.wikipedia.org/wiki/Collatz_猜想 )(对不起,朴素算法)

代码语言:javascript
运行
复制
#include "shiftsc.hpp"

using namespace std;

using element = unsigned;
using length = unsigned;

length compute_length(element n)
  {return n == 1 ? 1 : (1 + compute_length(n % 2 == 0 ? n / 2 : n * 3 + 1));}

int main()
{
  constexpr element max_element = 100;

  // one-indexed std::array<length, max_element>
  shifted_SequenceContainer<array<length, max_element>, 1> Collatz_lengths;
  // or for short: shifted_array<length, max_element, 1> Collatz_lengths;

  for(element i = 1; i <= max_element; i++)
    Collatz_lengths[i] = compute_length(i);
}

见工作:http://ideone.com/Xy8A2U

(稍后,我将在一个单独的问题中,为运行时偏移的变化提供一个用例-我对另一个需要使用此功能的包装器有一个想法。)

问题及其解决方案:

在向您介绍代码之前,我必须先写下一些我可以看到的问题--我不知道如何修复…(inb4近距离投票:他们不会让代码被破坏!)

  • 代码的长度。这太搞笑了。然而,我几乎无能为力:编写容器需要定义大量不同的方法,尽管其中大多数方法的代码很简单,但它们的数量使这段代码长达453行。对于这个问题,我想出了不同的“解决方案”,但没有一种解决方案奏效:·为容器包装器定义一个基类-- virtual与模板不兼容的b/c是不可能的(不能允许重载方法,比如template <class Iterator> void assign (Iterator it, Iterator jt);·用宏定义重复方法和整个类;这确实有效,确实缩短了代码,但IMO使它完全不可读,所以我放弃了。)
  • std::array可以用大括号内的列表初始化;不幸的是,shifted_SequenceContainer<std::array</*...*/>/*...*/>不能.我对如何解决这个问题没有太多的想法。https://stackoverflow.com/questions/40599052/how-to-write-a-wrapper-for-stdarrays-list-initialization-constructor https://stackoverflow.com/questions/40599829/how-to-pass-a-braced-init-list-to-stdarray-s-constructor
  • 点名。Ikr,shifted_SequenceContainer打破了所有的命名约定…但我能做什么呢?这个概念叫做SequenceContainer,所以如果我改变了它,我就不再引用这个概念…它被称为SequenceContainer而不是sequence_container,因此像shifted_sequence_container这样的名称不合适,而像ShiftedSequenceContainer这样的名称与标准容器的命名不一致--毕竟,std::unordered_map被称为unordered_map,而不是UnorderedMap

代码:

(冗长的)序言已经够多了,下面是实际代码:

代码语言:javascript
运行
复制
#ifndef GAAZKAM_SHIFTSC_H
#define GAAZKAM_SHIFTSC_H

#include <utility>
#include <initializer_list>
#include <stdexcept>
#include <cstddef>
#include <array>
#include <vector>
#include <deque>

// Known problems: syntax like shifted_array<int, 4, 7> arr({1,2,3,4}) wont work

// With static offset

// Container must satisfy SequenceContainer
template<class Container, typename Container::difference_type Offset>
class shifted_SequenceContainer
{
public:
  using value_type = typename Container::value_type;
  using reference = typename Container::reference;
  using const_reference = typename Container::const_reference;
  using pointer = typename Container::pointer;
  using const_pointer = typename Container::const_pointer;
  using iterator = typename Container::iterator;
  using const_iterator = typename Container::const_iterator;
  using reverse_iterator = typename Container::reverse_iterator;
  using const_reverse_iterator = typename Container::const_reverse_iterator;
  using difference_type = typename Container::difference_type;
  using size_type = typename Container::size_type;

  using container_type = Container;

  // Must be public; otherwise the user mayn’t access e.g. vector::reserve,
  // which might be needed for optimization
  Container cont;

  static constexpr typename Container::difference_type offset = Offset;

  explicit shifted_SequenceContainer() {}
  shifted_SequenceContainer(shifted_SequenceContainer const &that)
    : cont(that.cont) {}
  shifted_SequenceContainer(shifted_SequenceContainer &&that)
    : cont(std::move(that.cont)) {}
  explicit shifted_SequenceContainer(Container const &that) : cont(that) {}
  explicit shifted_SequenceContainer(Container &&that) : cont(that) {}
  shifted_SequenceContainer &operator = (shifted_SequenceContainer const &that)
    {cont = that.cont; return *this;}
  shifted_SequenceContainer &operator = (shifted_SequenceContainer &&that)
    {cont = std::move(that.cont); return *this;}
  shifted_SequenceContainer &operator = (Container const &that)
    {cont = that; return *this;}
  shifted_SequenceContainer &operator = (Container &&that)
    {cont = std::move(that); return *this;}
  shifted_SequenceContainer
    (size_type n, value_type const &val = value_type())
    : cont(n, val) {}
  template<class Iterator> shifted_SequenceContainer(Iterator it, Iterator jt)
    : cont(it, jt) {}
  shifted_SequenceContainer(std::initializer_list<value_type> init) 
    : cont(init) {}
  shifted_SequenceContainer &operator = (std::initializer_list<value_type> init)
    {cont = init; return *this;}
  void assign(size_type n, value_type const &val) {return cont.assign(n, val);}
  template<class Iterator> void assign(Iterator it, Iterator jt)
    {return cont.assign(it, jt);}
  void assign(std::initializer_list<value_type> init)
    {return cont.assign(init);}
  void swap(shifted_SequenceContainer &that) {return cont.swap(that.cont);}
  friend void swap
    (shifted_SequenceContainer &lhs, shifted_SequenceContainer &rhs)
    {return swap(lhs.cont, rhs.cont);}

  friend bool operator ==
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont == rhs.cont;}
  friend bool operator != 
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont != rhs.cont;}
  friend bool operator <
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont < rhs.cont;}
  friend bool operator <=
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont <= rhs.cont;}
  friend bool operator >
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont > rhs.cont;}
  friend bool operator >=
    (shifted_SequenceContainer const &lhs, shifted_SequenceContainer const &rhs)
    {return lhs.cont >= rhs.cont;}

  constexpr size_type size() const {return cont.size();}
  constexpr size_type max_size() const {return cont.max_size();}
  void resize(size_type n) {return cont.resize(n);}
  void resize(size_type n, value_type const &val) {return cont.resize(n, val);}
  constexpr bool empty() const {return cont.empty();} 

  template<class ...Args> iterator emplace(const_iterator pos, Args &&...args)
    {return cont.emplace(pos, std::move(args...));}
  template<class ...Args> void emplace_front(Args &&...args)
    {return cont.emplace_front(std::move(args...));}
  template<class ...Args> void emplace_back(Args &&...args)
    {return cont.emplace_back(std::move(args...));}
  iterator insert(const_iterator pos, value_type const &val)
    {return cont.insert(pos, val);}
  iterator insert(const_iterator pos, value_type &&val)
    {return cont.insert(pos, std::move(val));}
  iterator insert(const_iterator pos, size_type n, value_type const &val)
    {return cont.insert(pos, n, val);}
  template<class Iterator> void insert(iterator pos, Iterator it, Iterator jt)
    {return cont.insert(pos, it, jt);}
  iterator insert(const_iterator pos, std::initializer_list<value_type> init)
    {return cont.insert(pos, init);}
  void push_front(value_type const &val) {return cont.push_front(val);}
  void push_front(value_type &&val) {return cont.push_front(std::move(val));}
  void push_back(value_type const &val) {return cont.push_back(val);}
  void push_back(value_type &&val) {return cont.push_back(std::move(val));}

  void clear() {return cont.clear();}
  iterator erase(const_iterator pos) {return cont.erase(pos);}
  iterator erase(const_iterator it, const_iterator jt)
    {return cont.erase(it, jt);}
  void pop_front() {return cont.pop_front();}
  void pop_back() {return cont.pop_back();}

  iterator begin() {return cont.begin();}
  constexpr const_iterator begin() const {return cont.begin();}  
  constexpr const_iterator cbegin() const {return cont.cbegin();}
  iterator end() {return cont.end();}
  constexpr const_iterator end() const {return cont.end();}
  constexpr const_iterator cend() const {return cont.cend();}
  reverse_iterator rbegin() {return cont.rbegin();}
  constexpr const_reverse_iterator rbegin() const {return cont.rbegin();}
  constexpr const_reverse_iterator crbegin() const {return cont.crbegin();}
  reverse_iterator rend() {return cont.rend();}
  constexpr const_reverse_iterator rend() const {return cont.rend();}
  constexpr const_reverse_iterator crend() const {return cont.crend();}
  reference front() {return cont.front();}
  constexpr const_reference front() const {return cont.front();}
  reference back() {return cont.back();}
  constexpr const_reference back() const {return cont.back();}

  // Here things actually start to change
  reference operator[] (difference_type pos)
    {return cont.operator[](pos-offset);}
  constexpr const_reference operator[] (difference_type pos) const
    {return cont.operator[](pos-offset);}
  reference at (difference_type pos)
    {if(pos-offset<0) throw std::out_of_range(""); return cont.at(pos-offset);}
  constexpr const_reference at (difference_type pos) const
    {if(pos-offset<0) throw std::out_of_range(""); return cont.at(pos-offset);}

  // Additionally let’s provide these ones:
  iterator find(difference_type pos)
    {return cont.begin()+(pos-offset);}
  constexpr const_iterator find(difference_type pos) const
    {return cont.cbegin()+(pos-offset);}
};

template
  <class T, std::size_t N, typename std::array<T, N>::difference_type offset>
using shifted_array = shifted_SequenceContainer<std::array<T, N>, offset>;

template<class T, typename std::vector<T>::difference_type offset>
using shifted_vector = shifted_SequenceContainer<std::vector<T>, offset>;

template<class T, typename std::deque<T>::difference_type offset>
using shifted_deque = shifted_SequenceContainer<std::deque<T>, offset>;

// With dynamic offset

// Container must satisfy SequenceContainer
template<class Container>
class dynshifted_SequenceContainer
{
public:
  using value_type = typename Container::value_type;
  using reference = typename Container::reference;
  using const_reference = typename Container::const_reference;
  using pointer = typename Container::pointer;
  using const_pointer = typename Container::const_pointer;
  using iterator = typename Container::iterator;
  using const_iterator = typename Container::const_iterator;
  using reverse_iterator = typename Container::reverse_iterator;
  using const_reverse_iterator = typename Container::const_reverse_iterator;
  using difference_type = typename Container::difference_type;
  using size_type = typename Container::size_type;

  using container_type = Container;

  // Must be public; otherwise the user mayn’t access e.g. vector::reserve,
  // which might be needed for optimization
  Container cont;
  difference_type offset = 0;

  explicit dynshifted_SequenceContainer() {}
  dynshifted_SequenceContainer(dynshifted_SequenceContainer const &that)
    : cont(that.cont), offset(that.offset) {}
  template<typename Container::difference_type StaticOffset>
  dynshifted_SequenceContainer
    (shifted_SequenceContainer<Container, StaticOffset> const &that)
    : cont(that.cont), offset(StaticOffset) {}
  dynshifted_SequenceContainer(dynshifted_SequenceContainer &&that)
    : cont(std::move(that.cont)), offset(that.offset) {}
  template<typename Container::difference_type StaticOffset>
  dynshifted_SequenceContainer
    (shifted_SequenceContainer<Container, StaticOffset> &&that)
    : cont(std::move(that.cont)), offset(StaticOffset) {}
  explicit dynshifted_SequenceContainer
    (Container const &that, difference_type off = difference_type{}) 
    : cont(that), offset(off) {}
  explicit dynshifted_SequenceContainer
    (Container &&that, difference_type off = difference_type{})
    : cont(that), offset(off) {}
  dynshifted_SequenceContainer &operator =
    (dynshifted_SequenceContainer const &that)
    {offset = that.offset; cont = that.cont; return *this;}
  template<typename Container::difference_type StaticOffset>
  dynshifted_SequenceContainer &operator =
    (shifted_SequenceContainer<Container, StaticOffset> const &that)
    {cont = that.cont; offset = StaticOffset; return *this;}
  dynshifted_SequenceContainer &operator = (dynshifted_SequenceContainer &&that)
    {offset = that.offset; cont = std::move(that.cont); return *this;}
  template<typename Container::difference_type StaticOffset>
  dynshifted_SequenceContainer &operator = 
    (shifted_SequenceContainer<Container, StaticOffset> &&that)
    {{cont = std::move(that.cont); offset = StaticOffset; return *this;}}
  dynshifted_SequenceContainer &operator = (Container const &that)
    {cont = that; return *this;}
  dynshifted_SequenceContainer &operator = (Container &&that)
    {cont = std::move(that); return *this;}
  explicit dynshifted_SequenceContainer
  (
    size_type n,
    value_type const &val = value_type(),
    difference_type offset = 0
  )
    : cont(n, val), offset(offset) {}
  explicit dynshifted_SequenceContainer(size_type n, difference_type offset)
    : cont(n, value_type{}), offset(offset) {}
  template<class Iterator> dynshifted_SequenceContainer
    (Iterator it, Iterator jt, difference_type offset = 0)
    : cont(it, jt), offset(offset) {}
  dynshifted_SequenceContainer
    (std::initializer_list<value_type> init, difference_type offset = 0)
    : cont(init) {}
  dynshifted_SequenceContainer &operator =
    (std::initializer_list<value_type> init)
    {cont = init; return *this;}
  void assign(size_type n, value_type const &val) {return cont.assign(n, val);}
  void assign(size_type n, value_type const &val, difference_type offset)
    {this->offset = offset; return cont.assign(n, val);}
  template<class Iterator> void assign(Iterator it, Iterator jt)
    {return cont.assign(it, jt);}
  template<class Iterator>
  void assign(Iterator it, Iterator jt, difference_type offset)
    {this.offset = offset; return cont.assign(it, jt);}
  void assign(std::initializer_list<value_type> init)
    {return cont.assign(init);}
  void assign(std::initializer_list<value_type> init, difference_type offset)
    {this.offset = offset; return cont.assign(init);}
  void swap(dynshifted_SequenceContainer &that)
    {std::swap(this->offset, that.offset); return cont.swap(that.cont);}
  friend void swap
    (dynshifted_SequenceContainer &lhs, dynshifted_SequenceContainer &rhs)
    {std::swap(lhs.offset, rhs.offset); return swap(lhs.cont, rhs.cont);}

  // I provide all those overloads despite the implicit conversion for
  // optimisation: implicit conversion is always linear, while those
  // overloads may sometimes evaluate in constant
  friend bool operator ==
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont == rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator ==
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset == rhs.offset && lhs.cont == rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator ==
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset == StaticOffset && lhs.cont == rhs.cont;}
  friend bool operator != 
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont != rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator !=
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset != rhs.offset || lhs.cont != rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator !=
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset != StaticOffset || lhs.cont != rhs.cont;}
  friend bool operator < 
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont < rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator <
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset < rhs.offset || lhs.cont < rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator <
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset < StaticOffset || lhs.cont < rhs.cont;}
  friend bool operator <= 
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont <= rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator <=
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset <= rhs.offset || lhs.cont <= rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator <=
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset <= StaticOffset || lhs.cont <= rhs.cont;}
  friend bool operator > 
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont > rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator >
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset > rhs.offset || lhs.cont > rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator >
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset > StaticOffset || lhs.cont > rhs.cont;}
  friend bool operator >= 
  (
    dynshifted_SequenceContainer const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return lhs.cont >= rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator >=
  (
    shifted_SequenceContainer<Container, StaticOffset> const &lhs,
    dynshifted_SequenceContainer const &rhs
  )
    {return StaticOffset >= rhs.offset || lhs.cont >= rhs.cont;}
  template<typename Container::difference_type StaticOffset>
  friend bool operator >=
  (
    dynshifted_SequenceContainer const &lhs,
    shifted_SequenceContainer<Container, StaticOffset> const &rhs
  )
    {return lhs.offset >= StaticOffset || lhs.cont >= rhs.cont;}


  constexpr size_type size() const {return cont.size();}
  constexpr size_type max_size() const {return cont.max_size();}
  void resize(size_type n) {return cont.resize(n);}
  void resize(size_type n, value_type const &val) {return cont.resize(n, val);}
  constexpr bool empty() const {return cont.empty();} 

  template<class ...Args> iterator emplace(const_iterator pos, Args &&...args)
    {return cont.emplace(pos, std::move(args...));}
  template<class ...Args> void emplace_front(Args &&...args)
    {return cont.emplace_front(std::move(args...));}
  template<class ...Args> void emplace_back(Args &&...args)
    {return cont.emplace_back(std::move(args...));}
  iterator insert(const_iterator pos, value_type const &val)
    {return cont.insert(pos, val);}
  iterator insert(const_iterator pos, value_type &&val)
    {return cont.insert(pos, std::move(val));}
  iterator insert(const_iterator pos, size_type n, value_type const &val)
    {return cont.insert(pos, n, val);}
  template<class Iterator> void insert(iterator pos, Iterator it, Iterator jt)
    {return cont.insert(pos, it, jt);}
  iterator insert(const_iterator pos, std::initializer_list<value_type> init)
    {return cont.insert(pos, init);}
  void push_front(value_type const &val) {return cont.push_front(val);}
  void push_front(value_type &&val) {return cont.push_front(std::move(val));}
  void push_back(value_type const &val) {return cont.push_back(val);}
  void push_back(value_type &&val) {return cont.push_back(std::move(val));}

  void clear() {return cont.clear();}
  iterator erase(const_iterator pos) {return cont.erase(pos);}
  iterator erase(const_iterator it, const_iterator jt)
    {return cont.erase(it, jt);}
  void pop_front() {return cont.pop_front();}
  void pop_back() {return cont.pop_back();}

  iterator begin() {return cont.begin();}
  constexpr const_iterator begin() const {return cont.begin();}  
  constexpr const_iterator cbegin() const {return cont.cbegin();}
  iterator end() {return cont.end();}
  constexpr const_iterator end() const {return cont.end();}
  constexpr const_iterator cend() const {return cont.cend();}
  reverse_iterator rbegin() {return cont.rbegin();}
  constexpr const_reverse_iterator rbegin() const {return cont.rbegin();}
  constexpr const_reverse_iterator crbegin() const {return cont.crbegin();}
  reverse_iterator rend() {return cont.rend();}
  constexpr const_reverse_iterator rend() const {return cont.rend();}
  constexpr const_reverse_iterator crend() const {return cont.crend();}
  reference front() {return cont.front();}
  constexpr const_reference front() const {return cont.front();}
  reference back() {return cont.back();}
  constexpr const_reference back() const {return cont.back();}
  reference operator[] (difference_type pos)
    {return cont.operator[](pos-offset);}
  constexpr const_reference operator[] (difference_type pos) const
    {return cont.operator[](pos-offset);}
  reference at (difference_type pos)
    {if(pos-offset<0) throw std::out_of_range(""); return cont.at(pos-offset);}
  constexpr const_reference at (difference_type pos) const
    {if(pos-offset<0) throw std::out_of_range(""); return cont.at(pos-offset);}
  iterator find(difference_type pos)
    {return cont.begin()+(pos-offset);}
  constexpr const_iterator find(difference_type pos) const
    {return cont.cbegin()+(pos-offset);}
};

template<class T, std::size_t N>
using dynshifted_array = dynshifted_SequenceContainer<std::array<T, N>>;

template<class T>
using dynshifted_vector = dynshifted_SequenceContainer<std::vector<T>>;

template<class T>
using dynshifted_deque = dynshifted_SequenceContainer<std::deque<T>>;

#endif

我是很喜欢这样做的,我对编程非常熟悉,所以我非常感谢你的评论。提前感谢!

EN

回答 1

Code Review用户

发布于 2016-11-18 13:25:59

我相信你花了太多的精力去解决一些不应该成为问题的事情。简单地说,总是让容器以零为基础,例如,如果您有基于1的索引作为输入,只需在得到输入后立即从它们中减去1,并在输出之前将其转换回来。始终在内部使用基于零的索引,并且只在尽可能接近输入/输出时进行转换。

(太大了,实在评论不了)

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/147365

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档