Commit 236e44aa2b4716f79d669f083b1b040b991cd591

Authored by Grzegorz Jabłoński
1 parent 9b4ab1c1

Added c++17 fold expression example

examples11/05-foldexpr/makefile 0 → 100644
  1 +all: testvector
  2 +
  3 +testvector: testvector.cpp vector.h
  4 + g++ -std=c++17 -g -Wall -pedantic $< -o $@
  5 +
  6 +.PHONY: clean
  7 +
  8 +clean:
  9 + -rm testvector
0 10 \ No newline at end of file
... ...
examples11/05-foldexpr/testvector.cpp 0 → 100644
  1 +#include <iostream>
  2 +using namespace std;
  3 +#include "vector.h"
  4 +
  5 +template<class C> void printvector (vector<C> v)
  6 +{
  7 + cout << v << endl;
  8 +}
  9 +
  10 +int
  11 +main ()
  12 +{
  13 + vector<int> a (10);
  14 + cout << a << endl;
  15 + a[0] = 15;
  16 + a[5] = 32;
  17 + vector<int> b(10);
  18 + a.push_back(4);
  19 + a.push_back(5);
  20 + a.push_back(6);
  21 + a.push_back(7);
  22 + a.push_back(8);
  23 + a.push_back(9);
  24 + a.push_back(10);
  25 + a.push_back(11);
  26 + a.push_back(12,13,14);
  27 + int arg = 15;
  28 + a.push_back(arg);
  29 + b=a;
  30 + printvector (b);
  31 +
  32 +}
... ...
examples11/05-foldexpr/vector.h 0 → 100644
  1 +#ifndef __VECTOR_H__
  2 +#define __VECTOR_H__
  3 +#include <cstring>
  4 +#include <limits>
  5 +#include <type_traits>
  6 +
  7 +template <class C> class vector {
  8 + C *data;
  9 + unsigned int size;
  10 + unsigned int cap;
  11 +
  12 +private:
  13 + static unsigned int round_up_to_power_of_2(unsigned w) {
  14 + const auto bits = std::numeric_limits<unsigned>::digits;
  15 + --w;
  16 + for (unsigned s = 1; s < bits; s *= 2)
  17 + w |= w >> s;
  18 + return ++w;
  19 + };
  20 +
  21 + void destroy_array(C *ptr, unsigned int s) {
  22 + for (unsigned j = 0; j < s; ++j)
  23 + (ptr + j)->~C();
  24 + free(ptr);
  25 + }
  26 +
  27 + void resize_before_push() {
  28 + if (size >= cap) {
  29 + if (cap > std::numeric_limits<decltype(size)>::max() / (2 * sizeof(C)))
  30 + throw bad_alloc();
  31 + unsigned int newcap = (cap == 0) ? 1 : 2 * cap;
  32 + C *newdata;
  33 + if constexpr (!std::is_trivially_copyable<C>()) {
  34 + newdata = static_cast<C *>(
  35 + std::aligned_alloc(alignof(C), newcap * sizeof(C)));
  36 + if (!newdata)
  37 + throw bad_alloc();
  38 + unsigned i;
  39 + try {
  40 + for (i = 0; i < size; i++)
  41 + new (newdata + i) C(std::move(data[i]));
  42 + } catch (...) {
  43 + destroy_array(newdata, i);
  44 + throw;
  45 + }
  46 + destroy_array(data, size);
  47 + } else {
  48 + newdata = static_cast<C *>(std::realloc(data, newcap * sizeof(C)));
  49 + if (!newdata)
  50 + throw bad_alloc();
  51 + }
  52 + data = newdata;
  53 + cap = newcap;
  54 + }
  55 + }
  56 +
  57 +public:
  58 + class index_out_of_range {};
  59 + explicit vector(unsigned s) {
  60 +
  61 + cap = round_up_to_power_of_2(s);
  62 +
  63 + data = static_cast<C *>(std::aligned_alloc(alignof(C), cap * sizeof(C)));
  64 + if (!data)
  65 + throw bad_alloc();
  66 + size = s;
  67 +
  68 + unsigned i;
  69 + try {
  70 + for (i = 0; i < size; i++)
  71 + new (data + i) C();
  72 + } catch (...) {
  73 + destroy_array(data, i);
  74 + throw;
  75 + }
  76 + }
  77 +
  78 + ~vector() { destroy_array(data, size); }
  79 +
  80 + C &operator[](unsigned int pos) {
  81 + if (pos >= size)
  82 + throw index_out_of_range();
  83 + return data[pos];
  84 + }
  85 +
  86 + C operator[](unsigned int pos) const {
  87 + if (pos >= size)
  88 + throw index_out_of_range();
  89 + return data[pos];
  90 + }
  91 +
  92 + vector(const vector<C> &s) {
  93 + cap = s.cap;
  94 + data = static_cast<C *>(std::aligned_alloc(alignof(C), cap * sizeof(C)));
  95 + if (!data)
  96 + throw bad_alloc();
  97 + size = s.size;
  98 + unsigned i;
  99 + try {
  100 + for (i = 0; i < size; i++)
  101 + new (data + i) C(s.data[i]);
  102 + } catch (...) {
  103 + destroy_array(data, i);
  104 + throw;
  105 + }
  106 + }
  107 +
  108 + void swap(vector<C> &s) {
  109 + C *t1 = s.data;
  110 + unsigned int t2 = s.size;
  111 + unsigned int t3 = s.cap;
  112 + s.data = data;
  113 + s.size = size;
  114 + data = t1;
  115 + size = t2;
  116 + cap = t3;
  117 + }
  118 +
  119 + vector<C> &operator=(const vector<C> &s) {
  120 + if (this == &s)
  121 + return *this;
  122 + vector<C> n(s);
  123 + swap(n);
  124 + return *this;
  125 + }
  126 + friend ostream &operator<<(ostream &o, const vector<C> &v) {
  127 + o << '[';
  128 + for (unsigned i = 0; i < v.size; i++) {
  129 + o << v[i];
  130 + if (i != v.size - 1)
  131 + o << ',';
  132 + };
  133 + o << ']';
  134 + return o;
  135 + }
  136 +
  137 + template <class... Args> C &emplace_back(Args &&... args) {
  138 + // cout << "emplace_back" << endl;
  139 + resize_before_push();
  140 + new (data + size) C(std::forward<Args>(args)...);
  141 + ++size;
  142 + return *(data + size);
  143 + }
  144 +
  145 +private:
  146 + template <class T> C &push_back_single(T &&s) {
  147 + resize_before_push();
  148 + new (data + size) C(std::forward<T>(s));
  149 + ++size;
  150 + return *(data + size);
  151 + }
  152 +public:
  153 +
  154 + template <class... Args> C &push_back(Args &&... args) {
  155 + return (push_back_single(std::forward<Args>(args)), ...);
  156 + }
  157 +
  158 +
  159 +};
  160 +#endif /* __VECTOR_H__ */
... ...