Страницы

Поиск по вопросам

вторник, 9 апреля 2019 г.

Умный указатель и массив

Задача поставлена следующим образом: создать класс умный указатель, с которым можно будет реализовать следующее:
int main() { SmartPointer p1 = new int(2); p1->Method1(); p1[2] = int(); // должна быть ошибка на этапе компиляции SmartPointer p2 = new int[3]; p2->Method1(); //должна быть ошибка на этапе компиляции p2[2] = int(); return 0; }
если создаем объект Object = new Object(3); - тогда мы можем обратиться с помощью стрелки ко всем методам которыми обладает объект Object если мы создали массив объект Object = new Object[3] - тогда мы не можем обратиться с помощью стрелки к массиву.
Код ниже:
template class SmartPointer { private: DefaultDeleter m_deleter;
Counter *m_count = nullptr; T *m_ptr = nullptr;
typedef std::remove_all_extents_t ptr;
public: SmartPointer(T* const ptr) : m_count(new Counter), m_ptr(ptr) { m_count->incrementCount(); }
SmartPointer(const SmartPointer &source) m_count(source.m_count), m_ptr(source.m_ptr) { m_count->incrementCount(); }
SmartPointer& operator=(const SmartPointer &right) { m_count->decrementCount(); return SmartPointer(right).Swap(*this); } T& operator*() { return *m_ptr; } T* operator->() { return m_ptr; } T& operator[](unsigned int index) { return m_ptr[index]; }
SmartPointer& Swap(SmartPointer& other) { std::swap(m_ptr, other.m_ptr); return *this; } ~SmartPointer() { { m_count->decrementCount(); if (m_count->getCount() == 0) { m_deleter.Delete(m_ptr); delete m_count; } } } };
template class DefaultDeleter { public: void Delete(T* const ptr) { delete ptr; } };
template class DefaultDeleter { public: void Delete(T* const ptr) { delete[] ptr; } };
class Counter { private: unsigned int m_uses=0; public: void incrementCount() { ++m_uses; } void decrementCount() { --m_uses; } unsigned int getCount() { return m_uses; } };
Не совсем понятно как сделать так что бы компилятор понимал где (), а где [] где один элемент, а где массив элементов + как исправить ошибку в этой строке кода:
SmartPointer p2 = new int[3];


Ответ

Вам нужно просто сделать два разных класса: один для массива, другой - для скаляра. Так же это сделано для std::unique_ptr. Пример:
template struct smartPtr { T* operator->() { return ptr; } T* ptr; };
template struct smartPtr { T& operator[](int i) { return ptr[i]; } T* ptr; };
struct A { void foo() {} };
int main() { smartPtr ip; ip->foo(); ip[0]; // error
smartPtr ia; ia->foo(); // error ia[0].foo(); }

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

Отправить комментарий