diff --git a/json11.cpp b/json11.cpp index 9647846..b0f9341 100644 --- a/json11.cpp +++ b/json11.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include namespace json11 { @@ -46,6 +48,41 @@ struct NullStruct { bool operator<(NullStruct) const { return false; } }; +/* NoDestructor + * + * Wrapper that makes it easy to create an object of type T with static storage duration that: + * - is only constructed on first access + * - never invokes the destructor + */ +template +class NoDestructor { +public: + template + explicit NoDestructor(Args&&... args) { + new (storage_) T(std::forward(args)...); + } + + 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(storage_); } + T* get() { return reinterpret_cast(storage_); } + +private: + alignas(T) char storage_[sizeof(T)]; +}; + /* * * * * * * * * * * * * * * * * * * * * Serialization */ @@ -236,14 +273,14 @@ struct Statics { }; static const Statics & statics() { - static const Statics s {}; - return s; + static const NoDestructor s; + return *s; } static const Json & static_null() { // This has to be separate, not in Statics, because Json() accesses statics().null. - static const Json json_null; - return json_null; + static const NoDestructor json_null; + return *json_null; } /* * * * * * * * * * * * * * * * * * * *