Advertisement
Guest User

Untitled

a guest
Dec 9th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.08 KB | None | 0 0
  1. #ifndef CONTAINERS_HPP_
  2. #define CONTAINERS_HPP_
  3.  
  4. #include <functional>
  5. #include <fstream>
  6.  
  7. namespace containers
  8. {
  9.  
  10. template <typename T>
  11. struct Node
  12. {
  13. Node<T> *next;
  14. T value;
  15.  
  16. explicit Node(T v, Node<T> *n) : next{n}, value{v} {}
  17. };
  18.  
  19. template <typename T>
  20. class Container
  21. {
  22. protected:
  23. Node<T> *head;
  24. Node<T> *tail;
  25.  
  26. private:
  27. template <typename X = T, typename std::enable_if<std::is_arithmetic<X>::value, X>::type* = nullptr>
  28. static const std::function<T(const std::string&)> create_convert()
  29. {
  30. static auto c = [](const std::string &s) { return std::stoi(s); };
  31. return c;
  32. }
  33.  
  34. template <typename X = T, typename std::enable_if<std::is_same<X, std::string>::value, X>::type* = nullptr>
  35. static const std::function<T(const std::string&)> create_convert()
  36. {
  37. static auto c = [](const std::string &s) { return s; };
  38. return c;
  39. }
  40.  
  41. const std::function<T(const std::string&)> convert = create_convert();
  42.  
  43. public:
  44. Container() : head{nullptr}, tail{nullptr} {}
  45.  
  46. virtual void push(T i) = 0;
  47.  
  48. virtual ~Container()
  49. {
  50. auto tmp = head;
  51. while (tmp) {
  52. auto next = tmp->next;
  53. delete tmp;
  54. tmp = next;
  55. }
  56. }
  57.  
  58. bool empty() const
  59. {
  60. return head == nullptr;
  61. }
  62.  
  63. void load(std::string filepath)
  64. {
  65. std::string s;
  66. std::ifstream f;
  67. f.open(filepath);
  68. while (std::getline(f, s))
  69. push(convert(s));
  70. }
  71.  
  72. void save(std::string filepath) const
  73. {
  74. std::ifstream f;
  75. f.open(filepath);
  76. map([&f](const T& i) { f << i << '\n'; });
  77. f.close();
  78. }
  79.  
  80. void map(std::function<void(T)> f) const
  81. {
  82. for(auto i = head; i; i = i->next)
  83. f(i->value);
  84. }
  85.  
  86. void map(std::function<void(T&)> f)
  87. {
  88. for(auto i = head; i; i = i->next)
  89. f(i->value);
  90. }
  91.  
  92. void map(std::function<void(const T&)> f) const
  93. {
  94. for(auto i = head; i; i = i->next)
  95. f(i->value);
  96. }
  97.  
  98. };
  99.  
  100. template <typename T>
  101. class Stack : public Container<T>
  102. {
  103. using Container<T>::head;
  104.  
  105. void deepcopy(Node<T> *n)
  106. {
  107. if(n) {
  108. deepcopy(n->next);
  109. push(n->value);
  110. }
  111. }
  112.  
  113. public:
  114. Stack() : Container<T>{} {}
  115.  
  116. template <typename ... Args>
  117. Stack(Args ... args) : Container<T>{}
  118. {
  119. push(args...);
  120. }
  121.  
  122. Stack(const Stack &other) : Container<T>{}
  123. {
  124. deepcopy(other.head);
  125. }
  126.  
  127. Stack& operator=(const Stack &other) = default;
  128.  
  129. template <typename ... Args>
  130. void push(T i, Args ... args)
  131. {
  132. push(i);
  133. push(args...);
  134. }
  135.  
  136. void push(T i)
  137. {
  138. head = new Node<T>{i, head};
  139. }
  140.  
  141. T pop()
  142. {
  143. if(this->empty()) return T{};
  144. auto tmp = head;
  145. auto v = tmp->value;
  146. head = head->next;
  147. delete tmp;
  148. return v;
  149. }
  150.  
  151. };
  152.  
  153. template <typename T>
  154. class Queue : public Container<T>
  155. {
  156. using Container<T>::head;
  157. using Container<T>::tail;
  158.  
  159. void deepcopy(Node<T> *n)
  160. {
  161. if(n) {
  162. push(n->value);
  163. deepcopy(n->next);
  164. }
  165. }
  166.  
  167. public:
  168. Queue() : Container<T>{} {}
  169.  
  170. template <typename ... Args>
  171. Queue(Args ... args) : Container<T>{}
  172. {
  173. push(args...);
  174. }
  175.  
  176. Queue(const Queue &other) : Container<T>{}
  177. {
  178. deepcopy(other.head);
  179. }
  180.  
  181. Queue& operator=(const Queue &other) = default;
  182.  
  183. template <typename ... Args>
  184. void push(T i, Args ... args)
  185. {
  186. push(i);
  187. push(args...);
  188. }
  189.  
  190. void push(T i)
  191. {
  192. if (this->empty()) {
  193. auto tmp = new Node<T>{i, head};
  194. head = tail = tmp;
  195. } else {
  196. auto tmp = new Node<T>{i, nullptr};
  197. tail->next = tmp;
  198. tail = tmp;
  199. }
  200. }
  201.  
  202. T pop()
  203. {
  204. if(this->empty()) return T{};
  205. auto tmp = head;
  206. auto v = tmp->value;
  207. head = head->next;
  208. if (this->empty())
  209. tail = nullptr;
  210. delete tmp;
  211. return v;
  212. }
  213.  
  214. };
  215.  
  216. // "And now for the tricky bit" - Robert Virding
  217. //
  218. // Sfortunatamente non sono riusito ad implementare SFINAE utilizzando il C++
  219. // 11. L'idea è di poter restringe i tipi accetatti dal template secondo una
  220. // discriminante. In questo caso la discriminante sarebbe la possibilità di
  221. // poter utilizzare gli operatori di confronto booleani sul tipo di parametro
  222. // passato.
  223. //
  224. // In C++ 17:
  225. //
  226. // template <typename T,
  227. // typename = std::enable_if_t<
  228. // std::disjunction_v<std::is_arithmetic<T>, std::is_member_function_pointer<decltype(&T::operator==)>>>>
  229. //
  230. // Mentre in C++ 20 utilizzando i concetti:
  231. //
  232. // template <typename T> requires requires { &T::operator<=>; }
  233. //
  234. // Questo codice al fallimento produrebbe un errore simile:
  235. //
  236. // no member named 'operator<=>' in 'Foo'
  237. //
  238. // Decisamente molto più leggibile rispetto al libro di errori prodotto da del codice che non utilizza ne SFINAE ne concetti:
  239. //
  240. // In file included from main.cpp:1:containers.hpp: In instantiation of ‘static const std::function<bool(const T&, const T&)> containers::List<T>::create_compare() [with T = containers::Stack<int>]’:
  241. // containers.hpp:262:72: required from ‘containers::List<T>::List() [with T = containers::Stack<int>]’
  242. // main.cpp:7:19: required from here
  243. // containers.hpp:258:71: error: no match for ‘operator<’ (operand types are ‘const containers::Stack<int>’ and ‘const containers::Stack<int>’)
  244. // 258 | static auto c = [](const T &lhs, const T &rhs) -> bool { return lhs < rhs; };
  245. // | ~~~~^~~~~
  246. // In file included from /usr/include/c++/9.2.0/functional:59,
  247. // from containers.hpp:4,
  248. // from main.cpp:1:
  249. // /usr/include/c++/9.2.0/bits/std_function.h:669:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = containers::List<T>::create_compare() [with T = containers::Stack<int>]::<lambda(const containers::Stack<int>&, const containers::Stack<int>&)>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = bool; _ArgTypes = {const containers::Stack<int>&, const containers::Stack<int>&}]’, declared using local type ‘containers::List<T>::create_compare() [with T = containers::Stack<int>]::<lambda(const containers::Stack<int>&, const containers::Stack<int>&)>’, is used but never defined [-fpermissive]
  250. // 669 | function<_Res(_ArgTypes...)>::
  251. // | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  252. //
  253. template <typename T>
  254. class List : public Container<T>
  255. {
  256. using Container<T>::head;
  257.  
  258. static const std::function<bool(const T&, const T&)> create_compare()
  259. {
  260. static auto c = [](const T &lhs, const T &rhs) -> bool { return lhs > rhs; };
  261. return c;
  262. }
  263.  
  264. const std::function<bool(const T&, const T&)> compare = create_compare();
  265.  
  266. void deepcopy(Node<T> *n)
  267. {
  268. if(n) {
  269. push(n->value);
  270. deepcopy(n->next);
  271. }
  272. }
  273.  
  274. public:
  275. List() : Container<T>{} {}
  276.  
  277. List(std::function<bool(const T&, const T&)> compare_) : Container<T>{} , compare{compare_} {}
  278.  
  279. template <typename ... Args>
  280. List(T i, Args ... args) : Container<T>{}
  281. {
  282. push(i);
  283. push(args...);
  284. }
  285.  
  286. List(const List &other) : Container<T>{}
  287. {
  288. deepcopy(other.head);
  289. }
  290.  
  291. List& operator=(const List &other) = default;
  292.  
  293. template <typename ... Args>
  294. void push(T i, Args ... args)
  295. {
  296. push(i);
  297. push(args...);
  298. }
  299.  
  300. void push(T i)
  301. {
  302. if (this->empty() || !compare(i, head->value)) {
  303. head = new Node<T>{i, head};
  304. } else {
  305. Node<T> *cur = head;
  306. while (cur->next && compare(i, cur->next->value)) cur = cur->next;
  307. cur->next = new Node<T>{i, cur->next};
  308. }
  309. }
  310.  
  311. T pop()
  312. {
  313. return pop(1);
  314. }
  315.  
  316. /// \Brief Return element at position pos; index starts from 1.
  317. T pop(int pos)
  318. {
  319. if (this->empty()) return T{};
  320. if (pos == 1) {
  321. auto tmp = head;
  322. auto v = head->value;
  323. head = head->next;
  324. delete tmp;
  325. return v;
  326. } else {
  327. auto cur = head;
  328. for (int i = 2; i < pos && cur->next; ++i, cur = cur->next);
  329. if (!cur->next) return T{};
  330. auto tmp = cur->next;
  331. auto v = cur->next->value;
  332. cur->next = cur->next->next;
  333. delete tmp;
  334. return v;
  335. }
  336. }
  337.  
  338. /// \Brief Delete element from list
  339. void erase(int v)
  340. {
  341. int index = 1;
  342. for (auto i = head; i; i = i->next, ++index)
  343. if (i->value == v)
  344. pop(index);
  345. }
  346.  
  347. };
  348.  
  349. } // namespace containers
  350.  
  351. #endif /* CONTAINERS_HPP_ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement