| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| #ifndef TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED |
| #define TWOBLUECUBES_CATCH_CONSTRUCTOR_HPP_INCLUDED |
|
|
| #include <type_traits> |
|
|
| namespace Catch { |
| namespace Benchmark { |
| 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: |
| |
| template <typename U> |
| void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); } |
| |
| 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)); |
| } |
|
|
| T const& stored_object() const { |
| 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 |
|
|