繁体   English   中英

通过范围检查和带符号的size_type扩展std :: vector

[英]Extend std::vector with range checking and signed size_type

我想使用与std :: vector具有相同功能的类,但是

  • std::vector<T>::size_type替换为一些带符号的整数(例如int64_t或简称int ),而不是通常的size_t 当我使用标准矢量接口时,看到编译器在有符号数和无符号数之间进行比较时会产生警告,这非常令人讨厌。 我不能仅禁用此类警告,因为它们确实有助于捕获编程错误。
  • assert(0 <= i && i < size()); 内部operator[](int i)来检查超出范围的错误。 据我了解,与调用.at()这将是一个更好的选择,因为我可以在发行版本中禁用断言,因此性能将与向量的标准实现相同。 对于我来说,几乎不可能在每次操作之前都没有手动检查范围的情况下使用std::vector ,因为operator[]是几乎所有与内存访问相关的奇怪错误的源头。

我想到的可能的选择是

  1. 从std :: vector继承。 如以下问题所述,这不是一个好主意: 通过继承扩展C ++标准库?
  2. 使用composition(将std :: vector放入我的类中)并重复std::vector所有接口。 这个选项迫使我考虑当前的C ++标准,因为某些方法,迭代器的接口在C ++ 98、11、14、17中略有不同。 我想确定的是,当c ++ 20可用时,我可以简单地使用它,而无需重新实现我矢量的所有接口。

关于第1点,我们几乎从没有收到这些警告,因为我们在适当的地方使用了向量的size_type和/或在需要时将其强制转换(为安全起见,使用了诸如boost :: numeric_cast这样的“ checked”强制转换)。 那不是您的选择吗? 否则,编写一个函数为您完成此操作,即非const版本将类似于

template<class T>
T& ati(std::vector<T>& v, std::int64_t i)
{
  return v.at(checked_cast<decltype(v)::size_type>(i));
}

是的,继承仍然是一个问题。 即使不是,您也会破坏vector的定义(我猜想是Liskov替换原理),因为size_type被定义为

an unsigned integral type that can represent any non-negative value of difference_type

因此,取决于组合或一堆免费函数,这些函数可以使用带符号的size_type和范围检查进行访问。 就我个人而言,我会选择后者:工作量少,易于使用,并且您仍然可以将向量传递给功能强大的向量向量,而不会出现问题。

从注释中可以得到更多关于潜在问题的答案:

例如,我不知道如何以基于范围的方式编写:

for (int i = a.size() - 2; i >= 0; i--) { a[i] = 2 * a[i+1]; }

您可以将其更改为通用的,如下所示:

std::vector<int> vec1{ 1,2,3,4,5,6};
std::vector<int> vec2 = vec1;

int main()
{
    // generic code
    for ( auto it = vec1.rbegin()+1; it != vec1.rend(); it++ )
    {
       *it= 2* *(it-1);
    }

    // your code
    for (int i = vec2.size() - 2; i >= 0; i--)
    {
        vec2[i] = 2 * vec2[i+1];
    }

    for ( auto& el: vec1) { std::cout << el << std::endl; }
    for ( auto& el: vec2) { std::cout << el << std::endl; }
}

不使用基于的范围,因为它无法相对于位置进行访问。

(这不是真正的答案,而是注释,但是有一些代码,所以...)

对于第二部分(在运行时进行范围检查),第三个选项是使用一些宏技巧:

#ifdef DEBUG
  #define VECTOR_AT(v,i) v.at(i)
#else
  #define VECTOR_AT(v,i) v[i]
#endif

可以这样使用:

std::vector<sometype> vect(somesize);
VECTOR_AT(vect,i) = somevalue;

当然,这需要以一种非标准的方式来编辑代码,这可能不是一种选择。 但这确实起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM