diff --git a/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h b/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h index e362dc9a5..52299c14f 100644 --- a/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h +++ b/modules/common/chowdsp_core/Types/chowdsp_TypeTraits.h @@ -106,6 +106,18 @@ struct is_specialization_of, OuterType> final : std::true template class OuterType> static constexpr bool is_specialization_of_v = is_specialization_of::value; +template +struct is_complete_type +{ + template + static auto test (U*) -> std::integral_constant; + static auto test (...) -> std::false_type; + static constexpr auto value = ! std::is_same_v (nullptr))), std::false_type>; +}; + +template +static constexpr auto is_complete_type_v = is_complete_type::value; + /** * An empty struct intended to be used with std::conditional_t * to effectively "disable" some member of a struct/class. diff --git a/modules/common/chowdsp_data_structures/Structures/chowdsp_LocalPointer.h b/modules/common/chowdsp_data_structures/Structures/chowdsp_LocalPointer.h index a4167abc5..a39172667 100644 --- a/modules/common/chowdsp_data_structures/Structures/chowdsp_LocalPointer.h +++ b/modules/common/chowdsp_data_structures/Structures/chowdsp_LocalPointer.h @@ -4,6 +4,19 @@ namespace chowdsp { JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324) // structure was padded due to alignment specifier +#ifndef DOXYGEN +namespace local_pointer_detail +{ + template + constexpr size_t get_alignment() + { + if constexpr (is_complete_type_v) + return alignof (T); + return 8; + } +} // namespace local_pointer_detail +#endif + /** * A generic "owning" pointer constructed using local storage. * @@ -15,7 +28,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324) // structure was padded due to alignment * Make sure that no other type (e.g. std::unique_ptr) tries to take ownership * of the pointer being stored here, since that will result in a double-delete. */ -template +template ()> class LocalPointer { public: @@ -40,6 +53,7 @@ class LocalPointer jassert (pointer == nullptr); jassert (other.pointer == nullptr); juce::ignoreUnused (other); + return *this; } /** @@ -52,6 +66,8 @@ class LocalPointer C* emplace (Args&&... args) { static_assert (MaxSize >= sizeof (C), "Type is too large to fit into MaxSize bytes!"); + static_assert (Alignment % alignof (C) == 0, "Type alignments are incompatible!"); + reset(); pointer = new (data.data()) C (std::forward (args)...); return reinterpret_cast (pointer); diff --git a/tests/common_tests/chowdsp_core_test/TypeTraitsTest.cpp b/tests/common_tests/chowdsp_core_test/TypeTraitsTest.cpp index 3642b0670..08820a5c8 100644 --- a/tests/common_tests/chowdsp_core_test/TypeTraitsTest.cpp +++ b/tests/common_tests/chowdsp_core_test/TypeTraitsTest.cpp @@ -23,4 +23,11 @@ TEST_CASE ("Type Traits Test", "[common][types]") STATIC_REQUIRE (IsMapLike>); STATIC_REQUIRE (IsMapLike>); STATIC_REQUIRE_FALSE (IsMapLike>); + + struct A + { + }; + struct B; + STATIC_REQUIRE (chowdsp::is_complete_type_v); + STATIC_REQUIRE_FALSE (chowdsp::is_complete_type_v); } diff --git a/tests/common_tests/chowdsp_data_structures_test/LocalPointerTest.cpp b/tests/common_tests/chowdsp_data_structures_test/LocalPointerTest.cpp index 2e7f7d6a3..901291822 100644 --- a/tests/common_tests/chowdsp_data_structures_test/LocalPointerTest.cpp +++ b/tests/common_tests/chowdsp_data_structures_test/LocalPointerTest.cpp @@ -84,4 +84,29 @@ TEST_CASE ("Local Pointer Test", "[common][data-structures]") REQUIRE (ptr->xx == 45); REQUIRE (childPtr->yy == 46); } + + JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4324 4319) + static constexpr size_t testAlignment = 32; + SECTION ("Alignment Known") + { + struct alignas (testAlignment) Test + { + }; + chowdsp::LocalPointer ptr; + ptr.emplace(); + const auto alignedPtr = juce::snapPointerToAlignment (ptr.get(), testAlignment); + REQUIRE (alignedPtr == ptr.get()); + } + + SECTION ("Alignment Forward Declared") + { + chowdsp::LocalPointer ptr; + struct alignas (testAlignment) Test + { + }; + ptr.emplace(); + const auto alignedPtr = juce::snapPointerToAlignment (ptr.get(), testAlignment); + REQUIRE (alignedPtr == ptr.get()); + } + JUCE_END_IGNORE_WARNINGS_MSVC }