简体   繁体   English

C ++ - 基于赋值方重载[]运算符

[英]C++ - Overloading [] operators based on the side of assignment

I'm trying to write a dynamic array template in c++ 我正在尝试用c ++编写动态数组模板

I'm currently overloading the [] operators and I'd like to implement a different behavior based on which side of assignment they are used on. 我目前正在重载[]运算符,我想根据它们使用的赋值方面实现不同的行为。

#include <iostream>
...

template <class T>
T dynamic_array<T>::operator[](int idx) {
    return this->array[idx];
}

template <class T>
T& dynamic_array<T>::operator[](int idx) {
    return this->array[idx];
}

using namespace std;
int main() {
    dynamic_array<int>* temp = new dynamic_array<int>();

    // Uses the T& type since we are explicitly 
    // trying to modify the stored object
    (*temp)[0] = 1;

    // Uses the T type since nothing in the array 
    // should be modified outside the array
    int& b = (*temp)[0]; 

    // For instance...
    b = 4;
    cout<<(*temp)[0]; // Should still be 1
    return 0;
}

I get compiler errors when trying to overload like this for obvious reasons. 出于显而易见的原因,我在尝试像这样重载时遇到编译器错误。

Is there a proper way to do this? 有没有正确的方法来做到这一点?

My search so far has not been successful. 到目前为止,我的搜索还没有成功。 Anything I've seen with overloaded [] operators seems to accept that the user can modify the stored item outside of the object. 我在重载[]运算符中看到的任何东西似乎都接受用户可以修改对象外部的存储项。

I've implemented methods to use (instance(int i), update(int i, T obj)) but it would be nice to be able to use this class like a regular array. 我已经实现了使用的方法(实例(int i),更新(int i,T obj))但是能够像常规数组一样使用这个类会很好。

You cannot overload only on return type. 您不能仅在返回类型上重载。

The standard way to provide constant and non-constant accessor overloads is to differentiate by the constness of this : 提供恒定和非恒定存取过载的标准方法是通过的常量性来区分this

T       & get()       { return x; }
const T & get() const { return x; }  // or T get() const;

For the constant version, you can return either a const-reference or by value, depending on what T is - const-reference is probably more universally useful. 对于常量版本,您可以返回const-reference或value,具体取决于T是什么 - const-reference可能更普遍有用。

(In place of get() you would write operator[](std::size_t i) , of course. I just wanted to keep it short.) (当然,代替get()你会编写operator[](std::size_t i) 。我只是想保持简短。)


I don't think this achieves 100% what you had in mind, but that's because you have an error in your reasoning: int b = foo() will never be a reference to anything, even if foo() returns a (const or non-const) reference, because b is declared to be of type int , not int& . 我不认为这实现了你想到的100%,但这是因为你的推理有错误: int b = foo() 永远不会引用任何东西,即使foo()返回一个(const或非const)引用,因为b被声明为int类型,而不是int& Practically, you would actually call the non-const version when you say int b = (*temp)[0]; 实际上,当你说int b = (*temp)[0];时,你实际上会调用非const版本int b = (*temp)[0]; but that isn't actually a problem. 但这实际上不是问题。 (To get the constant version, you'd have to say int b = static_cast<const dynamic_array<int> &>(*temp)[0]; or (*static_cast<const dynamic_array<int> *>(temp))[0] - but why bother.) (要获得常量版本,您必须说int b = static_cast<const dynamic_array<int> &>(*temp)[0];或者(*static_cast<const dynamic_array<int> *>(temp))[0] - 但为什么要打扰。)

Scott Meyers talked about this in one of the Effective C++ books. Scott Meyers在其中一本Effective C ++书中谈到了这一点。 Basically the trick was to return a temporary const- or non-const proxy object from the index operators ( operator[]() and operator[]() const ), then overload the assignment and implicit conversion operators for that proxy class. 基本上诀窍是从索引运算符( operator[]()operator[]() const )返回临时的const或非const代理对象,然后重载该代理类的赋值和隐式转换运算符。 Something like this: 像这样的东西:

template <class T>
class Array
{
  public:
    struct proxy {
      T& element;

      proxy(T& el) : element(el) {}

      operator const T& () const {
        return element; // For use on RHS of assignment
      }

      proxy& operator=(const T& rhs) {
        // For use on LHS of assignment
        // Add your logic here
      }
    };

    const proxy operator[](int i) const {
      return proxy(a[i]);
    }

    proxy operator[](int i) {
      return proxy(a[i]);
    }

  private:
     T* a;
};

I may have some of the details wrong but the idea is to defer the decision of what side of the assignment the element is on until an actual attempt is made to assign to it. 我可能有一些细节错误,但想法是推迟决定元素所在的赋值的哪一方,直到实际尝试分配给它。 That is, you don't know what will be done at the time of the operator[] call, but you certainly do when you attempt to assign to the subsequent element reference. 也就是说,您不知道在operator []调用时将要执行的操作,但是当您尝试分配给后续元素引用时,您肯定会这样做。

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

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