如何实现std::array的绑定检查? 我已经扩展了C++ 11的STD::数组,它是工作文件,但是当我试图重载运算符[]时,我得到这个错误: error: lvalue required as left operand of assignment array[0] = 911; ^~~

如何实现std::array的绑定检查? 我已经扩展了C++ 11的STD::数组,它是工作文件,但是当我试图重载运算符[]时,我得到这个错误: error: lvalue required as left operand of assignment array[0] = 911; ^~~,c++,arrays,c++11,operator-overloading,C++,Arrays,C++11,Operator Overloading,是否可以实现运算符[]为std::数组类型添加绑定检查 代码如下: #include <array> #include <cassert> #include <iostream> template <unsigned int array_size, typename array_datatype=long int> struct Array : public std::array<array_datatype, array_size>

是否可以实现运算符[]为std::数组类型添加绑定检查

代码如下:

#include <array>
#include <cassert>
#include <iostream>

template <unsigned int array_size, typename array_datatype=long int>
struct Array : public std::array<array_datatype, array_size>
{
  Array()
  {
  }

  // std::array constructor inheritance
  // https://stackoverflow.com/questions/24280521/stdarray-constructor-inheritance
  Array(std::initializer_list< array_datatype > new_values)
  {
    unsigned int data_size = new_values.size();
    unsigned int column_index = 0;
    // std::cout << data_size << std::endl;

    if( data_size == 1 )
    {
      this->clear(*(new_values.begin()));
    }
    else
    {
      assert(data_size == array_size);

      for( auto column : new_values )
      {
        (*this)[column_index] = column;
        column_index++;
      }
    }
  }

  array_datatype operator[](unsigned int line)
  {
    assert(line < array_size);
    assert(line > -1);
    return (*this)[line];
  }

  /**
   * Prints a more beauty version of the array when called on `std::cout<< array << std::end;`
   */
  friend std::ostream& operator<<( std::ostream &output, const Array &array )
  {
    unsigned int column;
    output << "{";

    for( column=0; column < array_size; column++ )
    {
      output << array[column];

      if( column != array_size-1 )
      {
        output << ", ";
      }
    }

    output << "}";
    return output;
  }
}
相关的:

您可以使用:

array_datatype& operator[](unsigned int line)&
array_datatype const& operator[](unsigned int line)const&
array_datatype operator[](unsigned int line)&&
您可以使用:

array_datatype& operator[](unsigned int line)&
array_datatype const& operator[](unsigned int line)const&
array_datatype operator[](unsigned int line)&&

如果要在赋值的左侧使用运算符[]的返回值,则必须通过引用而不是通过值返回数组元素

您还有一个递归循环,因为您正在从自身内部调用自己的运算符[]。您希望调用基类的运算符[],因此需要对其进行限定

试试这个:

array_datatype& operator[](unsigned int line)
{
    assert(line < array_size);
    assert(line > -1);
    return std::array<array_datatype, array_size>::operator[](line);
}

如果要在赋值的左侧使用运算符[]的返回值,则必须通过引用而不是通过值返回数组元素

您还有一个递归循环,因为您正在从自身内部调用自己的运算符[]。您希望调用基类的运算符[],因此需要对其进行限定

试试这个:

array_datatype& operator[](unsigned int line)
{
    assert(line < array_size);
    assert(line > -1);
    return std::array<array_datatype, array_size>::operator[](line);
}

如果希望对数组元素进行绑定检查访问,只需使用std::vector或std::array的at方法,而不是[]运算符。它就是为了这个目的而存在的,不要重新发明轮子:


有关数组边界检查的文档,请参阅。

如果希望对数组元素进行绑定检查访问,只需使用std::vector或std::array的at方法,而不是[]运算符。它就是为了这个目的而存在的,不要重新发明轮子:


有关数组边界检查的文档,请参阅。

这是我针对一维数组的解决方案:

#include <array>
#include <cassert>
#include <iostream>

template <unsigned int array_width, typename array_datatype=long int>
struct Array
{
  /**
   * Is it okay to inherit implementation from STL containers, rather than delegate?
   * https://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate
   */
  std::array<array_datatype, array_width> _data;

  /**
   * std::array constructor inheritance
   * https://stackoverflow.com/questions/24280521/stdarray-constructor-inheritance
   */
  Array()
  {
  }

  Array(std::initializer_list< array_datatype > new_values)
  {
    unsigned int data_size = new_values.size();
    unsigned int column_index = 0;
    // std::cout << data_size << std::endl;

    if( data_size == 1 )
    {
      this->clear(*(new_values.begin()));
    }
    else
    {
      assert(data_size == array_width);

      for( auto column : new_values )
      {
        this->_data[column_index] = column;
        column_index++;
      }
    }
  }

  /**
   * Overloads the `[]` array access operator, allowing you to access this class objects as the
   * where usual `C` arrays.
   *
   * How to implement bound checking for std::array?
   * https://stackoverflow.com/questions/49419089/how-to-implement-bound-checking-for-stdarray
   *
   * @param  line the current line you want to access
   * @return      a pointer to the current line
   */
  array_datatype operator[](unsigned int line)&&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  array_datatype const& operator[](unsigned int line)const&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  array_datatype& operator[](unsigned int line)&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  void clear(array_datatype initial = 0)
  {
    unsigned int column_index = 0;

    for( ; column_index < array_width; column_index++ )
    {
      this->_data[column_index] = initial;
    }
  }

  /**
   * The Array<> type includes the Matrix<> type, because you can multiply a `Array` by an `Matrix`,
   * but not a vice-versa.
   */
  void multiply(Array< array_width, Array< array_width, array_datatype > > &matrix)
  {
    unsigned int column;
    unsigned int step;

    array_datatype old_array[array_width];

    for(column = 0; column < array_width; column++)
    {
      old_array  [column] = this->_data[column];
      this->_data[column] = 0;
    }

    for(column = 0; column < array_width; column++)
    {
      for(step = 0; step < array_width; step++)
      {
        this->_data[column] += old_array[step] * matrix._data[step][column];
      }
    }
    // If you would like to preserve the original value, it can be returned here
    // return old_array;
  }

  /**
   * Prints a more beauty version of the array when called on `std::cout<< array << std::end;`
   */
  friend std::ostream& operator<<( std::ostream &output, const Array &array )
  {
    unsigned int column;
    output << "{";

    for( column=0; column < array_width; column++ )
    {
      output << array._data[column];

      if( column != array_width-1 )
      {
        output << ", ";
      }
    }

    output << "}";
    return output;
  }
};

这是我针对一维阵列的解决方案:

#include <array>
#include <cassert>
#include <iostream>

template <unsigned int array_width, typename array_datatype=long int>
struct Array
{
  /**
   * Is it okay to inherit implementation from STL containers, rather than delegate?
   * https://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate
   */
  std::array<array_datatype, array_width> _data;

  /**
   * std::array constructor inheritance
   * https://stackoverflow.com/questions/24280521/stdarray-constructor-inheritance
   */
  Array()
  {
  }

  Array(std::initializer_list< array_datatype > new_values)
  {
    unsigned int data_size = new_values.size();
    unsigned int column_index = 0;
    // std::cout << data_size << std::endl;

    if( data_size == 1 )
    {
      this->clear(*(new_values.begin()));
    }
    else
    {
      assert(data_size == array_width);

      for( auto column : new_values )
      {
        this->_data[column_index] = column;
        column_index++;
      }
    }
  }

  /**
   * Overloads the `[]` array access operator, allowing you to access this class objects as the
   * where usual `C` arrays.
   *
   * How to implement bound checking for std::array?
   * https://stackoverflow.com/questions/49419089/how-to-implement-bound-checking-for-stdarray
   *
   * @param  line the current line you want to access
   * @return      a pointer to the current line
   */
  array_datatype operator[](unsigned int line)&&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  array_datatype const& operator[](unsigned int line)const&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  array_datatype& operator[](unsigned int line)&
  {
    assert(line < array_width);
    assert(line >= 0);
    return this->_data[line];
  }

  void clear(array_datatype initial = 0)
  {
    unsigned int column_index = 0;

    for( ; column_index < array_width; column_index++ )
    {
      this->_data[column_index] = initial;
    }
  }

  /**
   * The Array<> type includes the Matrix<> type, because you can multiply a `Array` by an `Matrix`,
   * but not a vice-versa.
   */
  void multiply(Array< array_width, Array< array_width, array_datatype > > &matrix)
  {
    unsigned int column;
    unsigned int step;

    array_datatype old_array[array_width];

    for(column = 0; column < array_width; column++)
    {
      old_array  [column] = this->_data[column];
      this->_data[column] = 0;
    }

    for(column = 0; column < array_width; column++)
    {
      for(step = 0; step < array_width; step++)
      {
        this->_data[column] += old_array[step] * matrix._data[step][column];
      }
    }
    // If you would like to preserve the original value, it can be returned here
    // return old_array;
  }

  /**
   * Prints a more beauty version of the array when called on `std::cout<< array << std::end;`
   */
  friend std::ostream& operator<<( std::ostream &output, const Array &array )
  {
    unsigned int column;
    output << "{";

    for( column=0; column < array_width; column++ )
    {
      output << array._data[column];

      if( column != array_width-1 )
      {
        output << ", ";
      }
    }

    output << "}";
    return output;
  }
};

这确实需要一些解释。第三个看起来非常可选,除非它将绑定到从函数调用返回的auto&@lili literal数组,否则使用[]获取元素,按值返回是正确的。例如,处理引用生存期扩展。这确实需要一些解释。第三个看起来非常可选,除非它将绑定到从函数调用返回的auto&@lili literal数组,否则使用[]获取元素,按值返回是正确的。例如,处理引用生存期延长。请注意的风险。您还应注意使用assertline>-1;对Francois来说,从POD类或聚合类派生出general通常是一个坏主意,也是一个错误的设计。数组是一个POD类。没有构造函数,没有赋值方法,没有虚函数,没有虚析构函数等等。它可能是功能性的,但这是一种危险的设计,不推荐使用。@FERcsI,你能参考一些解释它是如何危险的吗?如果你在原POD类的基础上创建一个新的POD类,应该没有问题。但由于不建议使用POD作为基类,理论上它可能导致未定义的行为。但是,如果您打破此限制并创建构造函数、析构函数、赋值运算符,编译器的行为可能会与预期不同。请注意的风险。您还应注意使用assertline>-1;对Francois来说,从POD类或聚合类派生出general通常是一个坏主意,也是一个错误的设计。数组是一个POD类。没有构造函数,没有赋值方法,没有虚函数,没有虚析构函数等等。它可能是功能性的,但这是一种危险的设计,不推荐使用。@FERcsI,你能参考一些解释它是如何危险的吗?如果你在原POD类的基础上创建一个新的POD类,应该没有问题。但由于不建议使用POD作为基类,理论上它可能导致未定义的行为。然而,若你们打破这一点,创建构造函数、析构函数、赋值运算符,编译器的行为可能会和预期的不同。