1 /* 2 * Created by Joachim on 16/04/2019. 3 * Adapted from donated nonius code. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 // Constructor and destructor helpers 10 11 #ifndef TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED 12 #define TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED 13 14 #include <type_traits> 15 16 namespace Catch { 17 namespace Benchmark { 18 namespace Detail { 19 template <typename T, bool Destruct> 20 struct ObjectStorage 21 { 22 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type; 23 ObjectStorageCatch::Benchmark::Detail::ObjectStorage24 ObjectStorage() : data() {} 25 ObjectStorageCatch::Benchmark::Detail::ObjectStorage26 ObjectStorage(const ObjectStorage& other) 27 { 28 new(&data) T(other.stored_object()); 29 } 30 ObjectStorageCatch::Benchmark::Detail::ObjectStorage31 ObjectStorage(ObjectStorage&& other) 32 { 33 new(&data) T(std::move(other.stored_object())); 34 } 35 ~ObjectStorageCatch::Benchmark::Detail::ObjectStorage36 ~ObjectStorage() { destruct_on_exit<T>(); } 37 38 template <typename... Args> constructCatch::Benchmark::Detail::ObjectStorage39 void construct(Args&&... args) 40 { 41 new (&data) T(std::forward<Args>(args)...); 42 } 43 44 template <bool AllowManualDestruction = !Destruct> destructCatch::Benchmark::Detail::ObjectStorage45 typename std::enable_if<AllowManualDestruction>::type destruct() 46 { 47 stored_object().~T(); 48 } 49 50 private: 51 // If this is a constructor benchmark, destruct the underlying object 52 template <typename U> destruct_on_exitCatch::Benchmark::Detail::ObjectStorage53 void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } 54 // Otherwise, don't 55 template <typename U> destruct_on_exitCatch::Benchmark::Detail::ObjectStorage56 void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { } 57 stored_objectCatch::Benchmark::Detail::ObjectStorage58 T& stored_object() { 59 return *static_cast<T*>(static_cast<void*>(&data)); 60 } 61 stored_objectCatch::Benchmark::Detail::ObjectStorage62 T const& stored_object() const { 63 return *static_cast<T*>(static_cast<void*>(&data)); 64 } 65 66 67 TStorage data; 68 }; 69 } 70 71 template <typename T> 72 using storage_for = Detail::ObjectStorage<T, true>; 73 74 template <typename T> 75 using destructable_object = Detail::ObjectStorage<T, false>; 76 } 77 } 78 79 #endif // TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED 80