Как перегрузить operator[] для индексации элементов shared_ptr пользовательского векторного класса?

#c #operator-overloading #overloading #shared-ptr #square-bracket

#c #оператор-перегрузка #перегрузка #shared-ptr #квадратная скобка

Вопрос:

В настоящее время я создаю свой собственный векторный класс, и мне нравится создавать экземпляры любого класса с помощью общих указателей. Итак, есть ли способ перегрузки operator[] для достижения следующего кода?

 class myVector {
    public:
        myVector(/*some params*/);
        ~myVector();

        // Some kind of overloading of operator []

        // Some other code

    private:
        // private container array
        double* vec;

        // Some other code
};

int main ()
{
    std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));

    double val = sp[1];

    return 0;
}
  

Комментарии:

1. std::shared_ptr может использоваться для хранения массива, а затем вы можете получить доступ к элементам через operator[] . Если в shared_ptr нем не хранится массив, как в вашем случае, вы вообще не можете полагаться на объявление оператора.

2. Вы могли бы писать (*sp)[1] (разыменование, а затем доступ к индексу), если вы пишете operator[] перегрузку. См . en.cppreference.com/w/cpp/language/operators особенно в отношении оператора подстрочного индекса массива.

3. @NathanPierson Это было бы (*sp)[1] .

4. FWIW, наличие указателя на «управляемый контейнер» обычно не то, что вам нужно.

5. @krisz Спасибо за исправление приоритета оператора

Ответ №1:

Вы можете объявить [] оператор для своего myVector класса следующим образом (возвращая ссылку на элемент, чтобы у вас был доступ для чтения и записи):

 doubleamp; operator [] (int i)
{
    return vec[i];
}
  

Затем вы можете использовать этот оператор для объекта, на который указывает shared_ptr при первом разыменовании. Вот выполняемый пример, где я добавил некоторый «фиктивный» код в конструктор, просто чтобы заставить его что-то делать:

 #include <iostream>
#include <memory>

class myVector {
public:
    myVector(/*some params*/) {
        vec = new double[10];
        for (int i = 0; i < 10;   i) vec[i] = 3 * i;
    }
    ~myVector() {
        delete[] vec;
    }
    doubleamp; operator [] (int i) {
        return vec[i];
    }
 private:
    double* vec;
};

int main()
{
    std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));
    double val = (*sp)[6];
    std::cout << val << std::endl;
    (*sp)[4] = 312;
    std::cout << (*sp)[4] << std::endl;
    return 0;
}
  

Ответ №2:

Вы можете перегрузить оператор для класса следующим образом

 double amp; operator []( size_t i )
{
    return vec[i];
}
  

и

 const double amp; operator []( size_t i ) const
{
    return vec[i];
}
  

и назовите это как

 std::shared_ptr<myVector> sp = std::shared_ptr<myVector>(new myVector(/*some params*/));

//...

std::cout << ( *sp )[i] << 'n';
  

Комментарии:

1. @AdrianMole Они отличаются не только типами возвращаемых значений.

Ответ №3:

Я бы не стал этого делать в реальном приложении. Но просто для демонстрации, одна из возможностей достичь того, чего вы хотите (по крайней мере, технически), — это получить из std::shared_ptr и там объявить оператор индекса. Например:

 #include <memory>
#include <vector>
using namespace std;

template <class T>
class myshared_ptr;

template <class T >
class myshared_ptr<vector<T>> : public shared_ptr<vector<T>>
{
public:
    using elem_type = vector<T>;
    using shared_ptr<elem_type>::shared_ptr;
    using shared_ptr<elem_type>::operator*;
    using shared_ptr<elem_type>::get;
    
    typename elem_type::value_typeamp; operator[](size_t idx)
    {
        return (*get())[idx];
    }
};

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!n";
    auto p = myshared_ptr<vector<int>>(new vector<int>{1, 2, 3, 4});
    cout << p[2] << endl;
    return 0;
}
  

Живая демонстрация