From fb7228fcdb5016f010b4306938004bb0cab7c69a Mon Sep 17 00:00:00 2001 From: TJ Date: Wed, 15 Apr 2015 08:13:49 +0100 Subject: [PATCH] Use descriptive enums for method parameters --- DataStructures.hpp | 80 ++++++++++++++----------- GenericStorageContainerTemplateImpl.hpp | 60 ++++++++++++------- 2 files changed, 86 insertions(+), 54 deletions(-) diff --git a/DataStructures.hpp b/DataStructures.hpp index d88ec1c..4b186b1 100644 --- a/DataStructures.hpp +++ b/DataStructures.hpp @@ -32,27 +32,37 @@ namespace tj * Iterator to call common methods to perform store, retrieve, and search operations */ - // mnemonic alternatives to plain 'index' values - enum position { - BEGIN = 0, - END = -1, - TAIL = 0, - HEAD = -1 - }; - template class AbstractDataStructure { - protected: typedef AbstractDataStructure self_type; + protected: + + // shared pointer wraps actual data so that iterator instances can safely reference the same data std::shared_ptr data_; - size_t capacity_; - size_t size_; - size_t current_; + size_t capacity_; // storage allocated (in units of data type) + size_t size_; // storage used (in units of data type) + size_t current_; // index of active element (may not make sense for some data structures but is needed for API) public: + /* use descriptive symbols rather than booleans for method parameters */ + + // alternatives to numeric 'index' values + enum position { + BEGIN = 0, + END = -1, // newest + TAIL = 0, + HEAD = -1 // newest + }; + + // element erasure choices that evaluate to boolean states + enum erasure { + NO_ERASE, // false + ERASE // true + }; + AbstractDataStructure(size_t capacity = 0) : // use a lambda as the shared_ptr array deleter since the default deleter does not handle array deletion data_(new D[capacity_], []( D* p) {delete[] p; } ), @@ -66,25 +76,26 @@ namespace tj virtual ~AbstractDataStructure() {}; - /* API available to application + + /* API available to caller * * Some methods are pure virtual making this an Abstract (base) class * Sub-classes must implement these methods and over-ride others to * provide the specific storage class functionality */ - virtual size_t get_capacity() // available storage (in units of storage type) + virtual size_t get_capacity() // storage allocated (in units of data type) { return capacity_; }; - virtual size_t get_size() // used storage (in units of storage type) + virtual size_t get_size() // storage used (in units of data type) { return size_; }; /* the concepts of first, last, next and previous may not have a useful meaning in - * some storage classes e.g: 'previous' in a 1-way linked list (only has 'next'). + * some data structures e.g: 'previous' in a 1-way linked list (only has 'next'). */ virtual D* get_data() { @@ -102,15 +113,15 @@ namespace tj * * Depending on the data structure, values of index other than 0 or -1 may have no meaning and be ignored */ - virtual bool insert_at(D& data, long index = -1) = 0; + virtual bool insert_at(D& data, long index = HEAD) = 0; virtual bool insert(D& data) { - return insert_at(data, TAIL); + return this->insert_at(data, TAIL); }; virtual bool append(D& data) { - return insert_at(data, HEAD); + return this->insert_at(data); }; /* the remove operation can perform an optional erasure (delete) of the stored data. @@ -119,15 +130,15 @@ namespace tj */ // 'data' element at 'index' must satisfy equality - virtual bool remove_at(D& data, long index = -1, bool erase = false) = 0; // element matching 'data' at 'index' - virtual bool remove_at(long index = -1, bool erase = false) = 0; // any element at 'index' - virtual bool remove_all(D& data, bool erase = false) = 0; // all elements matching 'data' + virtual bool remove_at(D& data, long index = HEAD, bool erase = NO_ERASE) = 0; // element matching 'data' at 'index' + virtual bool remove_at(long index = HEAD, bool erase = NO_ERASE) = 0; // any element at 'index' + virtual bool remove_all(D& data, bool erase = NO_ERASE) = 0; // all elements matching 'data' /* the replace operation can perform an optional erasure (delete) of the current data element */ - virtual bool replace_at(D& data_in, D& data_out, long index = -1, bool erase = false) = 0; // element matching 'data_out' at 'index' - virtual bool replace_at(D& data_in, long index = -1, bool erase = false) = 0; // any element at 'index' - virtual bool replace_all(D& data_in, D& data_out, bool erase = false) = 0; // all elements matching 'data_out' + virtual bool replace_at(D& data_in, D& data_out, long index = HEAD, bool erase = NO_ERASE) = 0; // element matching 'data_out' at 'index' + virtual bool replace_at(D& data_in, long index = HEAD, bool erase = NO_ERASE) = 0; // any element at 'index' + virtual bool replace_all(D& data_in, D& data_out, bool erase = NO_ERASE) = 0; // all elements matching 'data_out' /* Search for an element matching 'needle'. The stored type must have defined @@ -177,6 +188,7 @@ namespace tj class DataStructure_ArrayDynamic : public AbstractDataStructure { typedef DataStructure_ArrayDynamic self_type; + typedef AbstractDataStructure BASE_CLASS; // alias for easier reading of enums size_t growth_; @@ -259,15 +271,15 @@ namespace tj return result; }; - virtual bool insert_at(AD& data, long index = TAIL) + virtual bool insert_at(AD& data, long index = BASE_CLASS::HEAD) { bool result = false; if (this->data_ != nullptr) { - if (index == TAIL) + if (index == BASE_CLASS::TAIL) index = 0; - else if (index == HEAD) + else if (index == BASE_CLASS::HEAD) index = this->size_; if (this->capacity_ <= index) @@ -287,42 +299,42 @@ namespace tj return result; }; - virtual bool remove_at(AD& data, long index = TAIL, bool erase = false) + virtual bool remove_at(AD& data, long index = BASE_CLASS::TAIL, bool erase = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement return result; }; - virtual bool remove_at(long index = TAIL, bool erase = false) + virtual bool remove_at(long index = BASE_CLASS::TAIL, bool erase = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement return result; }; - virtual bool remove_all(AD& data, bool eraser = false) + virtual bool remove_all(AD& data, bool eraser = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement return result; }; - virtual bool replace_at(AD& data_in, AD& data_out, long index = TAIL, bool erase = false) + virtual bool replace_at(AD& data_in, AD& data_out, long index = BASE_CLASS::TAIL, bool erase = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement return result; }; - virtual bool replace_at(AD& data_in, long index = TAIL, bool erase = false) + virtual bool replace_at(AD& data_in, long index = BASE_CLASS::TAIL, bool erase = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement return result; }; - virtual bool replace_all(AD& data_in, AD& data_out, bool erase = false) + virtual bool replace_all(AD& data_in, AD& data_out, bool erase = BASE_CLASS::NO_ERASE) { bool result = false; // TODO: implement diff --git a/GenericStorageContainerTemplateImpl.hpp b/GenericStorageContainerTemplateImpl.hpp index 104edb1..e63ff21 100644 --- a/GenericStorageContainerTemplateImpl.hpp +++ b/GenericStorageContainerTemplateImpl.hpp @@ -38,13 +38,19 @@ namespace tj * from a single iterator definition. Provides typedefs to make instantiating the * correct type of iterator easier to read and write in application code. * + * template parameters: + * T = type being stored + * DATA_STRUCTURE = class providing underlying storage of T elements, defaults to dynamic array + * + * For template template parameters see http://en.cppreference.com/w/cpp/language/template_parameters */ template class DATA_STRUCTURE = DataStructure_ArrayDynamic> class GenericStorageContainerTemplateImpl { - // attributes - - // data structure type is templated + // easy to read aliases + typedef AbstractDataStructure DS_BASE_CLASS; // for access to enums + + // data structure type is templated and decided by application code at compilation time DATA_STRUCTURE data_structure_; @@ -75,7 +81,7 @@ namespace tj iterator (DATA_STRUCTURE* element) : element_(element) {}; iterator (const iterator& copy) : element_(copy.element_) {}; // copy constructor - // ForwardIterator methods + /* ForwardIterator methods */ // postfix increment operator self_type operator++() @@ -101,7 +107,7 @@ namespace tj return *this; }; - // BidirectionalIterator methods + /* BidirectionalIterator methods */ // postfix decrement self_type operator--() @@ -120,7 +126,9 @@ namespace tj return *this; }; - // comparison methods + + /* Comparison */ + bool operator==(const self_type& right_hand_side) { bool result = false; @@ -131,6 +139,7 @@ namespace tj return result; }; + // implemented using operator==() bool operator!=(const self_type& right_hand_side) { return !this->operator==(right_hand_side); @@ -146,29 +155,33 @@ namespace tj return result; }; + // implemented using operator==() and operator<() bool operator<=(const self_type& right_hand_side) { return this->operator==(right_hand_side) | this->operator<(right_hand_side); }; - // data access + /* + * Data access */ + + // value-at T operator* () { - return element_ ? *element_->get_data() : 0; }; + // pointer-to std::conditional operator->() { return &element_->get_data(); }; - // allow const and non-const iterator copy-contructors access to private members + // allow const and non-const iterator copy-contructors access to private members of each other friend class iterator; }; // end of Iterator - // use these handy short-cuts in application code + // use these handy aliases in application code typedef iterator _const_iterator; typedef iterator _iterator; @@ -178,8 +191,8 @@ namespace tj * begin() and end() are used in code that instantiates the iterator: * * GSCTI container; - * container.insert(1); - * container.insert(2); + * container.append(1); + * container.append(2); * * for (_const_iterator i = container.begin(); i != container.end(); ++i) * { @@ -202,8 +215,10 @@ namespace tj { return iterator(data_structure_.get_end()); }; - - // object life-cycle + + + /* Object life-cycle */ + GenericStorageContainerTemplateImpl () {}; GenericStorageContainerTemplateImpl (const GenericStorageContainerTemplateImpl& copy) { @@ -214,36 +229,41 @@ namespace tj { }; - // capacity + + /* Capacity */ + + // storage allocated (in units of stored type) size_t get_capacity() { return data_structure_.get_capacity(); }; + // storage used (in units of stored type) size_t get_size() { return data_structure_.get_size(); }; - // modifiers + /* Modifiers */ - // append at tail + // append bool append(T& data) { return data_structure_.append(data); }; - // remove from tail + // remove bool remove() { - return false; + return data_structure_.remove_at(DS_BASE_CLASS::HEAD, DS_BASE_CLASS::NO_ERASE); }; }; // end of GenericStorageContainerTemplateImpl - // handy short-cuts for unweildy names + // GSCTI: handy alias for unweildy type name template class DS = DataStructure_ArrayDynamic> using GSCTI = GenericStorageContainerTemplateImpl< T, DS>; }; // end of namespace #endif + -- 2.17.1