shushus

Спринт 8. Проще и быстрее: std::array.

Feb 2nd, 2023
459
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.16 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. main.cpp
  3. -----------------------------------------------------------------------
  4. #include "log_duration.h"
  5. #include "my_assert.h"
  6. #include "stack_vector.h"
  7.  
  8. #include <iostream>
  9. #include <random>
  10. #include <stdexcept>
  11.  
  12. using namespace std;
  13.  
  14. void TestConstruction() {
  15.     StackVector<int, 10> v;
  16.     assert(v.Size() == 0u);
  17.     assert(v.Capacity() == 10u);
  18.  
  19.     StackVector<int, 8> u(5);
  20.     assert(u.Size() == 5u);
  21.     assert(u.Capacity() == 8u);
  22.  
  23.     try {
  24.         StackVector<int, 10> u(50);
  25.         cout << "Expect invalid_argument for too large size"s << endl;
  26.         assert(false);
  27.     } catch (invalid_argument&) {
  28.     } catch (...) {
  29.         cout << "Expect invalid_argument for too large size"s << endl;
  30.         assert(false);
  31.     }
  32. }
  33.  
  34. void TestPushBack() {
  35.     StackVector<int, 5> v;
  36.     for (size_t i = 0; i < v.Capacity(); ++i) {
  37.         v.PushBack(i);
  38.     }
  39.  
  40.     try {
  41.         v.PushBack(0);
  42.         cout << "Expect overflow_error for PushBack in full vector"s << endl;
  43.         assert(false);
  44.     } catch (overflow_error&) {
  45.     } catch (...) {
  46.         cout << "Unexpected exception for PushBack in full vector"s << endl;
  47.         assert(false);
  48.     }
  49. }
  50.  
  51. void TestPopBack() {
  52.     StackVector<int, 5> v;
  53.     for (size_t i = 1; i <= v.Capacity(); ++i) {
  54.         v.PushBack(i);
  55.     }
  56.     for (int i = v.Size(); i > 0; --i) {
  57.         assert(v.PopBack() == i);
  58.     }
  59.  
  60.     try {
  61.         v.PopBack();
  62.         cout << "Expect underflow_error for PopBack from empty vector"s << endl;
  63.         assert(false);
  64.     } catch (underflow_error&) {
  65.     } catch (...) {
  66.         cout << "Unexpected exception for PopBack from empty vector"s << endl;
  67.         assert(false);
  68.     }
  69. }
  70.  
  71. int main() {
  72.     TestConstruction();
  73.     TestPushBack();
  74.     TestPopBack();
  75.  
  76.     cerr << "Running benchmark..."s << endl;
  77.     const size_t max_size = 2500;
  78.  
  79.     default_random_engine re;
  80.     uniform_int_distribution<int> value_gen(1, max_size);
  81.  
  82.     vector<vector<int>> test_data(50000);
  83.     for (auto& cur_vec : test_data) {
  84.         cur_vec.resize(value_gen(re));
  85.         for (int& x : cur_vec) {
  86.             x = value_gen(re);
  87.         }
  88.     }
  89.  
  90.     {
  91.         LOG_DURATION("vector w/o reserve");
  92.         for (auto& cur_vec : test_data) {
  93.             vector<int> v;
  94.             for (int x : cur_vec) {
  95.                 v.push_back(x);
  96.             }
  97.         }
  98.     }
  99.     {
  100.         LOG_DURATION("vector with reserve");
  101.         for (auto& cur_vec : test_data) {
  102.             vector<int> v;
  103.             v.reserve(cur_vec.size());
  104.             for (int x : cur_vec) {
  105.                 v.push_back(x);
  106.             }
  107.         }
  108.     }
  109.     {
  110.         LOG_DURATION("StackVector");
  111.         for (auto& cur_vec : test_data) {
  112.             StackVector<int, max_size> v;
  113.             for (int x : cur_vec) {
  114.                 v.PushBack(x);
  115.             }
  116.         }
  117.     }
  118.     cerr << "Done"s << endl;
  119. }
  120. -----------------------------------------------------------------------
  121. log_duration.h
  122. -----------------------------------------------------------------------
  123. #pragma once
  124.  
  125. #include <chrono>
  126. #include <iostream>
  127.  
  128. #define PROFILE_CONCAT_INTERNAL(X, Y) X##Y
  129. #define PROFILE_CONCAT(X, Y) PROFILE_CONCAT_INTERNAL(X, Y)
  130. #define UNIQUE_VAR_NAME_PROFILE PROFILE_CONCAT(profileGuard, __LINE__)
  131. #define LOG_DURATION(x) LogDuration UNIQUE_VAR_NAME_PROFILE(x)
  132. #define LOG_DURATION_STREAM(x, y) LogDuration UNIQUE_VAR_NAME_PROFILE(x, y)
  133.  
  134. class LogDuration {
  135. public:
  136.  
  137.     using Clock = std::chrono::steady_clock;
  138.  
  139.     LogDuration(const std::string& id, std::ostream& dst_stream = std::cerr)
  140.         : id_(id)
  141.         , dst_stream_(dst_stream) {
  142.     }
  143.  
  144.     ~LogDuration() {
  145.         using namespace std::chrono;
  146.         using namespace std::literals;
  147.  
  148.         const auto end_time = Clock::now();
  149.         const auto dur = end_time - start_time_;
  150.         dst_stream_ << id_ << ": "s << duration_cast<milliseconds>(dur).count() << " ms"s << std::endl;
  151.     }
  152.  
  153. private:
  154.     const std::string id_;
  155.     const Clock::time_point start_time_ = Clock::now();
  156.     std::ostream& dst_stream_;
  157. };
  158. -----------------------------------------------------------------------
  159. my_assert.h
  160. -----------------------------------------------------------------------
  161. #pragma once
  162. #include <memory>
  163. #include <string>
  164.  
  165. namespace detail {
  166.  
  167. class AssertionFailed final {
  168. public:
  169.     AssertionFailed(std::string message, std::string file, std::string func, unsigned line)
  170.         : message_{std::move(message)}
  171.         , file_{std::move(file)}
  172.         , function_{std::move(func)}
  173.         , line_(line) {
  174.     }
  175.  
  176.     const std::string& GetMessage() const {
  177.         return message_;
  178.     }
  179.  
  180.     const std::string& GetFile() const {
  181.         return file_;
  182.     }
  183.  
  184.     const std::string& GetFunction() const {
  185.         return function_;
  186.     }
  187.  
  188.     unsigned GetLine() const {
  189.         return line_;
  190.     }
  191.  
  192. private:
  193.     std::string message_;
  194.     std::string file_;
  195.     std::string function_;
  196.     unsigned line_;
  197. };
  198.  
  199. inline void AssertImpl(const char* message, char const* file, char const* func, unsigned line) {
  200.     throw AssertionFailed(message, file, func, line);
  201. }
  202.  
  203. }  // namespace detail
  204.  
  205. #ifdef assert
  206. #undef assert
  207. #endif
  208.  
  209. #define assert(expression)   \
  210.     (void) ((!!(expression)) \
  211.             || (::detail::AssertImpl(#expression, __FILE__, __FUNCTION__, static_cast<unsigned>(__LINE__)), 0))
  212.  
  213. -----------------------------------------------------------------------
  214. stack_vector.h
  215. ----------------------------------------------------------------------
  216. #pragma once
  217.  
  218. #include <array>
  219. #include <stdexcept>
  220.  
  221. template <typename T, size_t N>
  222. class StackVector {
  223. public:
  224.     explicit StackVector(size_t a_size = 0){
  225.         if (a_size<= Capacity()) {
  226.             size_ = a_size;
  227.         }else{
  228.             throw std::invalid_argument("Invalid container size.");    
  229.         }
  230.     }
  231.  
  232.     T& operator[](size_t index){
  233.         return storage_.at(index);
  234.     }
  235.    
  236.     const T& operator[](size_t index) const{
  237.         return storage_.at(index);
  238.     }
  239.  
  240.     typename std::array<T, N>::iterator begin(){
  241.         return storage_.begin();
  242.     }
  243.    
  244.     typename std::array<T, N>::iterator end(){
  245.         return std::next(storage_.begin(), size_);
  246.     }
  247.    
  248.     typename std::array<T, N>::const_iterator begin() const{
  249.         return storage_.begin();
  250.     }
  251.    
  252.     typename std::array<T, N>::const_iterator end() const{
  253.         return std::next(storage_.begin(), size_);
  254.     }
  255.  
  256.     size_t Size() const{
  257.         return size_;
  258.     }
  259.     size_t Capacity() const{
  260.         return storage_.size();
  261.     }
  262.  
  263.     void PushBack(const T& value){
  264.         if(size_!=Capacity()) {
  265.             storage_[size_] = value;
  266.             ++size_;
  267.         }else{
  268.             throw std::overflow_error("Not enough free space to add a new item.");
  269.         }
  270.     }
  271.    
  272.     T PopBack(){
  273.         if(size_) {
  274.             --size_;
  275.             return storage_[size_];
  276.         }else{
  277.             throw std::underflow_error("Container is empty.");
  278.         }
  279.     }
  280. private:
  281.     std::array<T, N> storage_;
  282.     size_t size_;
  283. };
  284.  
Advertisement
Add Comment
Please, Sign In to add comment