// ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #ifndef FIXED_LIST_01238467085684139453534 #define FIXED_LIST_01238467085684139453534 #include namespace zen { //std::list(C++11) compatible class for inplace element construction supporting non-copyable/movable types //may be replaced by C++11 std::list when available template class FixedList { struct Node { Node() : next(nullptr), val() {} //no variadic templates on VC2010... :( template Node(A&& a) : next(nullptr), val(std::forward(a)) {} template Node(A&& a, B&& b) : next(nullptr), val(std::forward(a), std::forward(b)) {} template Node(A&& a, B&& b, C&& c) : next(nullptr), val(std::forward(a), std::forward(b), std::forward(c)) {} template Node(A&& a, B&& b, C&& c, D&& d) : next(nullptr), val(std::forward(a), std::forward(b), std::forward(c), std::forward(d)) {} template Node(A&& a, B&& b, C&& c, D&& d, E&& e) : next(nullptr), val(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e)) {} template Node(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f) : next(nullptr), val(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e), std::forward(f)) {} template Node(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f, G&& g) : next(nullptr), val(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e), std::forward(f), std::forward(g)) {} Node* next; //singly linked list is sufficient T val; }; public: FixedList() : first(nullptr), lastInsert(nullptr), sz(0) {} ~FixedList() { clear(); } template class ListIterator : public std::iterator { public: ListIterator(NodeT* it = nullptr) : iter(it) {} ListIterator& operator++() { iter = iter->next; return *this; } inline friend bool operator==(const ListIterator& lhs, const ListIterator& rhs) { return lhs.iter == rhs.iter; } inline friend bool operator!=(const ListIterator& lhs, const ListIterator& rhs) { return !(lhs == rhs); } U& operator* () { return iter->val; } U* operator->() { return &iter->val; } private: NodeT* iter; }; typedef T value_type; typedef ListIterator iterator; typedef ListIterator const_iterator; typedef T& reference; typedef const T& const_reference; iterator begin() { return first; } iterator end() { return iterator(); } const_iterator begin() const { return first; } const_iterator end () const { return const_iterator(); } const_iterator cbegin() const { return first; } const_iterator cend () const { return const_iterator(); } reference front() { return first->val; } const_reference front() const { return first->val; } reference& back() { return lastInsert->val; } const_reference& back() const { return lastInsert->val; } void emplace_back() { pushNode(new Node); } template void emplace_back(A&& a) { pushNode(new Node(std::forward(a))); } template void emplace_back(A&& a, B&& b) { pushNode(new Node(std::forward(a), std::forward(b))); } template void emplace_back(A&& a, B&& b, C&& c) { pushNode(new Node(std::forward(a), std::forward(b), std::forward(c))); } template void emplace_back(A&& a, B&& b, C&& c, D&& d) { pushNode(new Node(std::forward(a), std::forward(b), std::forward(c), std::forward(d))); } template void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e) { pushNode(new Node(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e))); } template void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f) { pushNode(new Node(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e), std::forward(f))); } template void emplace_back(A&& a, B&& b, C&& c, D&& d, E&& e, F&& f, G&& g) { pushNode(new Node(std::forward(a), std::forward(b), std::forward(c), std::forward(d), std::forward(e), std::forward(f), std::forward(g))); } template void remove_if(Predicate pred) { Node* prev = nullptr; Node* ptr = first; while (ptr) if (pred(ptr->val)) { Node* tmp = ptr->next; deleteNode(ptr); if (prev) prev->next = ptr = tmp; else first = ptr = tmp; if (!tmp) lastInsert = prev; } else { prev = ptr; ptr = ptr->next; } } void clear() { Node* ptr = first; while (ptr) { Node* tmp = ptr; ptr = ptr->next; delete tmp; } first = lastInsert = nullptr; sz = 0; } bool empty() const { return first == nullptr; } size_t size() const { return sz; } private: FixedList(const FixedList&); FixedList& operator=(const FixedList&); void pushNode(Node* newNode) //throw() { ++sz; if (lastInsert == nullptr) { assert(first == nullptr); first = lastInsert = newNode; } else { assert(lastInsert->next == nullptr); lastInsert->next = newNode; lastInsert = newNode; } } void deleteNode(Node* oldNode) { assert(sz > 0); --sz; delete oldNode; } Node* first; Node* lastInsert; //point to last insertion; required by efficient emplace_back() size_t sz; }; } #endif //FIXED_LIST_01238467085684139453534