Guest User

Untitled

a guest
Sep 23rd, 2021
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.32 KB | None | 0 0
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. namespace base {
  5.  
  6. class Clock {
  7.  public:
  8.   virtual int Now() = 0;
  9.   virtual ~Clock() {}
  10. };
  11.  
  12. class DefaultClock : public Clock {
  13.  public:
  14.   DefaultClock() {
  15.     std::cout << "Constructed DefaultClock" << std::endl;
  16.   }
  17.  
  18.   virtual ~DefaultClock() {
  19.     std::cout << "Destroyed DefaultClock" << std::endl;
  20.   }
  21.  
  22.   int Now() override {
  23.     static int now = 42;
  24.     return now++;
  25.   };
  26. };
  27.  
  28. class MockClock : public Clock {
  29.  public:
  30.   MockClock(int fixed) : fixed_(fixed), now_(fixed) {
  31.     std::cout << "Constructed MockClock" << fixed_ << std::endl;
  32.   }
  33.  
  34.   virtual ~MockClock() {
  35.     std::cout << "Destroyed MockClock" << fixed_ << std::endl;
  36.   }
  37.  
  38.   int Now() override { return now_; }
  39.  
  40.   void SetNow(int now) { now_ = now; }
  41.  private:
  42.   int fixed_;
  43.   int now_;
  44. };
  45.  
  46. template <typename T, typename O = std::nullptr_t>
  47. class NoDestructor {
  48.  public:
  49.   // Not constexpr; just write static constexpr T x = ...; if the value should
  50.   // be a constexpr.
  51.   template <typename... Args>
  52.   explicit NoDestructor(Args&&... args) {
  53.     new (storage_) T(std::forward<Args>(args)...);
  54.   }
  55.  
  56.   // Allows copy and move construction of the contained type, to allow
  57.   // construction from an initializer list, e.g. for std::vector.
  58.   explicit NoDestructor(const T& x) { new (storage_) T(x); }
  59.   explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
  60.  
  61.   NoDestructor(const NoDestructor&) = delete;
  62.   NoDestructor& operator=(const NoDestructor&) = delete;
  63.  
  64.   ~NoDestructor() = default;
  65.  
  66.   const T& operator*() const { return *get(); }
  67.   T& operator*() { return *get(); }
  68.  
  69.   const T* operator->() const { return get(); }
  70.   T* operator->() { return get(); }
  71.  
  72.   const T* get() const { return reinterpret_cast<const T*>(storage_); }
  73.   T* get() { return reinterpret_cast<T*>(storage_); }
  74.  
  75.  private:
  76.   alignas(T) char storage_[sizeof(T)];
  77. };
  78.  
  79. }
  80.  
  81. // Example class allowing to inject custom Clock.
  82. class Example {
  83.  public:
  84.    static void PrintNow() {
  85.      std::cout << GetClock().Now() << std::endl;
  86.    }
  87.    
  88.    static void SetClockForTesting(std::unique_ptr<base::Clock>& clock) {
  89.      GetClockPtr() = std::move(clock);
  90.    }
  91.  
  92.  private:
  93.   static std::unique_ptr<base::Clock>& GetClockPtr() {
  94.     static base::NoDestructor<std::unique_ptr<base::Clock>> clock([] {
  95.       return std::make_unique<base::DefaultClock>();
  96.     }());
  97.     return *clock;
  98.   }
  99.  
  100.   static base::Clock& GetClock() {
  101.     return *GetClockPtr().get();
  102.   }
  103. };
  104.  
  105. // Test code.
  106. void test() {
  107.     std::unique_ptr<base::Clock> mock_clock =
  108.       std::make_unique<base::MockClock>(11);
  109.     auto* raw_mock = static_cast<base::MockClock*>(mock_clock.get());
  110.     Example::SetClockForTesting(mock_clock);
  111.     Example::PrintNow();
  112.     raw_mock->SetNow(22);
  113. }
  114.  
  115.  
  116. int main() {
  117.   std::cout << "Start: nothing should be constructed before" << std::endl;
  118.   std::cout << "===========================================" << std::endl;
  119.   Example::PrintNow();
  120.   Example::PrintNow();
  121.   test();
  122.   Example::PrintNow();
  123.   std::unique_ptr<base::Clock> mock_clock =
  124.     std::make_unique<base::MockClock>(33);
  125.   Example::SetClockForTesting(mock_clock);
  126.   Example::PrintNow();
  127.   std::cout << "======================================" << std::endl;
  128.   std::cout << "End: nothing should be destroyed after" << std::endl;
  129. }
  130.  
Advertisement
Add Comment
Please, Sign In to add comment