#cpp #шаблоны_с++
Задача поставлена следующим образом: создать класс умный указатель, с которым можно
будет реализовать следующее:
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];
Ответы
Ответ 1
Вам нужно просто сделать два разных класса: один для массива, другой - для скаляра. Так же это сделано для std::unique_ptr. Пример: templatestruct 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(); }
Комментариев нет:
Отправить комментарий