From 3ba94edca7dc5965bd3e185a1e58630568c17897 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sun, 9 Sep 2012 16:25:20 +0200 Subject: [PATCH] menu: use shared pointers internally --- src/menu.h | 78 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/src/menu.h b/src/menu.h index 3e0ec84f..6e17ccac 100644 --- a/src/menu.h +++ b/src/menu.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "error.h" @@ -35,11 +36,14 @@ namespace NC { /// This template class is generic menu capable of /// holding any std::vector compatible values. -template struct Menu : public Window +template class Menu : public Window { + struct ItemProxy; + +public: struct Item { - friend struct Menu; + friend class Menu; Item() : m_is_bold(false), m_is_selected(false), m_is_inactive(false), m_is_separator(false) { } @@ -60,11 +64,11 @@ template struct Menu : public Window bool isSeparator() const { return m_is_separator; } private: - static Item *mkSeparator() + static Item mkSeparator() { - Item *i = new Item; - i->m_is_separator = true; - return i; + Item item; + item.m_is_separator = true; + return item; } T m_value; @@ -77,7 +81,7 @@ template struct Menu : public Window template class ItemIterator : public std::iterator { - friend struct Menu; + friend class Menu; BaseIterator m_it; explicit ItemIterator(BaseIterator it) : m_it(it) { } @@ -87,7 +91,7 @@ template struct Menu : public Window // version to be instantiated. static const bool referenceValue = !std::is_same< typename std::remove_const::type, - typename std::remove_pointer::type + typename BaseIterator::value_type::element_type >::value; template struct getObject { }; template struct getObject { @@ -144,20 +148,20 @@ template struct Menu : public Window }; typedef ItemIterator< - Item, typename std::vector::iterator + Item, typename std::vector::iterator > Iterator; typedef ItemIterator< - const Item, typename std::vector::const_iterator + const Item, typename std::vector::const_iterator > ConstIterator; typedef std::reverse_iterator ReverseIterator; typedef std::reverse_iterator ConstReverseIterator; typedef ItemIterator< - T, typename std::vector::iterator + T, typename std::vector::iterator > ValueIterator; typedef ItemIterator< - typename std::add_const::type, typename std::vector::const_iterator + typename std::add_const::type, typename std::vector::const_iterator > ConstValueIterator; typedef std::reverse_iterator ReverseValueIterator; @@ -181,8 +185,8 @@ template struct Menu : public Window Menu(size_t startx, size_t starty, size_t width, size_t height, const std::string &title, Color color, Border border); - /// Destroys the object and frees memory - virtual ~Menu(); + Menu(const Menu &) = delete; + Menu &operator=(const Menu &) = delete; /// Sets helper function that is responsible for displaying items /// @param ptr function pointer that matches the ItemDisplayer prototype @@ -399,6 +403,22 @@ template struct Menu : public Window ConstReverseValueIterator rendV() const { return ConstReverseValueIterator(beginV()); } private: + struct ItemProxy + { + typedef Item element_type; + + ItemProxy() { } + ItemProxy(Item &&item) : m_ptr(std::make_shared(item)) { } + + Item &operator*() const { return *m_ptr; } + Item *operator->() const { return m_ptr.get(); } + + bool operator==(const ItemProxy &rhs) const { return m_ptr == rhs.m_ptr; } + + private: + std::shared_ptr m_ptr; + }; + bool isHighlightable(size_t pos) { return !(*m_options_ptr)[pos]->isSeparator() && !(*m_options_ptr)[pos]->isInactive(); @@ -409,9 +429,9 @@ private: FilterFunction m_filter; FilterFunction m_searcher; - std::vector *m_options_ptr; - std::vector m_options; - std::vector m_filtered_options; + std::vector *m_options_ptr; + std::vector m_options; + std::vector m_filtered_options; std::set m_found_positions; size_t m_beginning; @@ -448,12 +468,6 @@ template Menu::Menu(size_t startx, { } -template Menu::~Menu() -{ - for (auto it = m_options.begin(); it != m_options.end(); ++it) - delete *it; -} - template void Menu::reserve(size_t size_) { m_options.reserve(size_); @@ -463,22 +477,18 @@ template void Menu::resizeList(size_t new_size) { if (new_size > m_options.size()) { + size_t old_size = m_options.size(); m_options.resize(new_size); - for (size_t i = 0; i < new_size; ++i) - if (!m_options[i]) - m_options[i] = new Item(); + for (size_t i = old_size; i < new_size; ++i) + m_options[i] = Item(); } - else if (new_size < m_options.size()) - { - for (size_t i = new_size; i < m_options.size(); ++i) - delete m_options[i]; + else m_options.resize(new_size); - } } template void Menu::addItem(const T &item, bool is_bold, bool is_inactive) { - m_options.push_back(new Item(item, is_bold, is_inactive)); + m_options.push_back(Item(item, is_bold, is_inactive)); } template void Menu::addSeparator() @@ -488,7 +498,7 @@ template void Menu::addSeparator() template void Menu::insertItem(size_t pos, const T &item, bool is_bold, bool is_inactive) { - m_options.insert(m_options.begin()+pos, new Item(item, is_bold, is_inactive)); + m_options.insert(m_options.begin()+pos, Item(item, is_bold, is_inactive)); } template void Menu::insertSeparator(size_t pos) @@ -680,8 +690,6 @@ template void Menu::reset() template void Menu::clear() { - for (auto it = m_options.begin(); it != m_options.end(); ++it) - delete *it; clearFilterResults(); m_options.clear(); m_found_positions.clear();