Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <memory>
- namespace base {
- class Clock {
- public:
- virtual int Now() = 0;
- virtual ~Clock() {}
- };
- class DefaultClock : public Clock {
- public:
- DefaultClock() {
- std::cout << "Constructed DefaultClock" << std::endl;
- }
- virtual ~DefaultClock() {
- std::cout << "Destroyed DefaultClock" << std::endl;
- }
- int Now() override {
- static int now = 42;
- return now++;
- };
- };
- class MockClock : public Clock {
- public:
- MockClock(int fixed) : fixed_(fixed), now_(fixed) {
- std::cout << "Constructed MockClock" << fixed_ << std::endl;
- }
- virtual ~MockClock() {
- std::cout << "Destroyed MockClock" << fixed_ << std::endl;
- }
- int Now() override { return now_; }
- void SetNow(int now) { now_ = now; }
- private:
- int fixed_;
- int now_;
- };
- template <typename T, typename O = std::nullptr_t>
- class NoDestructor {
- public:
- // Not constexpr; just write static constexpr T x = ...; if the value should
- // be a constexpr.
- template <typename... Args>
- explicit NoDestructor(Args&&... args) {
- new (storage_) T(std::forward<Args>(args)...);
- }
- // Allows copy and move construction of the contained type, to allow
- // construction from an initializer list, e.g. for std::vector.
- explicit NoDestructor(const T& x) { new (storage_) T(x); }
- explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
- NoDestructor(const NoDestructor&) = delete;
- NoDestructor& operator=(const NoDestructor&) = delete;
- ~NoDestructor() = default;
- const T& operator*() const { return *get(); }
- T& operator*() { return *get(); }
- const T* operator->() const { return get(); }
- T* operator->() { return get(); }
- const T* get() const { return reinterpret_cast<const T*>(storage_); }
- T* get() { return reinterpret_cast<T*>(storage_); }
- private:
- alignas(T) char storage_[sizeof(T)];
- };
- }
- // Example class allowing to inject custom Clock.
- class Example {
- public:
- static void PrintNow() {
- std::cout << GetClock().Now() << std::endl;
- }
- static void SetClockForTesting(std::unique_ptr<base::Clock>& clock) {
- GetClockPtr() = std::move(clock);
- }
- private:
- static std::unique_ptr<base::Clock>& GetClockPtr() {
- static base::NoDestructor<std::unique_ptr<base::Clock>> clock([] {
- return std::make_unique<base::DefaultClock>();
- }());
- return *clock;
- }
- static base::Clock& GetClock() {
- return *GetClockPtr().get();
- }
- };
- // Test code.
- void test() {
- std::unique_ptr<base::Clock> mock_clock =
- std::make_unique<base::MockClock>(11);
- auto* raw_mock = static_cast<base::MockClock*>(mock_clock.get());
- Example::SetClockForTesting(mock_clock);
- Example::PrintNow();
- raw_mock->SetNow(22);
- }
- int main() {
- std::cout << "Start: nothing should be constructed before" << std::endl;
- std::cout << "===========================================" << std::endl;
- Example::PrintNow();
- Example::PrintNow();
- test();
- Example::PrintNow();
- std::unique_ptr<base::Clock> mock_clock =
- std::make_unique<base::MockClock>(33);
- Example::SetClockForTesting(mock_clock);
- Example::PrintNow();
- std::cout << "======================================" << std::endl;
- std::cout << "End: nothing should be destroyed after" << std::endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment