/* * Created by Joachim on 16/04/2019. * Adapted from donated nonius code. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ // Constructor and destructor helpers #ifndef TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED #include <type_traits> namespace Catch { namespace Detail { template <typename T, bool Destruct> struct ObjectStorage { using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; ObjectStorage() : data() {} ObjectStorage(const ObjectStorage& other) { new(&data) T(other.stored_object()); } ObjectStorage(ObjectStorage&& other) { new(&data) T(std::move(other.stored_object())); } ~ObjectStorage() { destruct_on_exit<T>(); } template <typename... Args> void construct(Args&&... args) { new (&data) T(std::forward<Args>(args)...); } template <bool AllowManualDestruction = !Destruct> typename std::enable_if<AllowManualDestruction>::type destruct() { stored_object().~T(); } private: // If this is a constructor benchmark, destruct the underlying object template <typename U> void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } // Otherwise, don't template <typename U> void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } T& stored_object() { return *static_cast<T*>(static_cast<void*>(&data)); } TStorage data; }; } template <typename T> using storage_for = Detail::ObjectStorage<T, true>; template <typename T> using destructable_object = Detail::ObjectStorage<T, false>; } #endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED