diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c04e8e..f4a87a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ message(STATUS "IRIS_ROOT: ${IRIS_ROOT}") # Handle with care, keep these to the ones that can't be # accomplished by target-specific settings. +set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + set(CMAKE_COLOR_DIAGNOSTICS ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -195,7 +197,7 @@ if(MSVC) target_compile_options( _iris_cxx_best_practices INTERFACE - /W4 /analyze /analyze:external- + /W4 $<$:/Zi /Zo> ) target_link_options( diff --git a/include/iris/rvariant/detail/variant_storage.hpp b/include/iris/rvariant/detail/variant_storage.hpp index 658ef66..04874f3 100644 --- a/include/iris/rvariant/detail/variant_storage.hpp +++ b/include/iris/rvariant/detail/variant_storage.hpp @@ -8,7 +8,8 @@ // IWYU pragma: private, include #include -#include + +#include #include #include @@ -101,22 +102,41 @@ template // Additional size limit inline constexpr std::size_t never_valueless_trivial_size_limit = 256; +template +concept is_never_valueless_impl = + is_ttp_specialization_of_v || + ( + sizeof(T) <= never_valueless_trivial_size_limit && + std::is_trivially_destructible_v && + ( + std::is_trivially_move_constructible_v || + std::is_trivially_copy_constructible_v + ) && + ( + std::is_trivially_move_assignable_v || + std::is_trivially_copy_assignable_v + ) + ); + template -struct is_never_valueless - : std::conjunction< - std::disjunction< - is_ttp_specialization_of, - std::conjunction< - std::bool_constant, - std::is_trivially_destructible, - std::disjunction, std::is_trivially_copy_constructible>, - std::disjunction, std::is_trivially_copy_assignable> - > - >... +struct is_never_valueless; + +template<> +struct is_never_valueless<> : std::true_type {}; + +template + requires is_never_valueless_impl +struct is_never_valueless + : std::bool_constant< + is_never_valueless::value > -{ - static_assert(sizeof...(Ts) > 0); -}; +{}; + +template + requires (!is_never_valueless_impl) +struct is_never_valueless + : std::false_type +{}; template constexpr bool is_never_valueless_v = is_never_valueless::value; @@ -131,13 +151,17 @@ template struct variadic_union {}; template -using make_variadic_union_t = variadic_union...>, Ts...>; - +using make_variadic_union_t = variadic_union< + (std::is_trivially_destructible_v && ...), + Ts... +>; template struct variadic_union { +#if IRIS_CI static_assert(std::conjunction_v, std::is_trivially_destructible...>); +#endif static constexpr std::size_t size = sizeof...(Ts) + 1; static constexpr bool never_valueless = is_never_valueless_v; @@ -174,9 +198,11 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END template - requires (I != 0) && std::is_constructible_v, std::in_place_index_t, Args...> + requires + (I > 0) && (I < size) && + std::is_constructible_v constexpr explicit variadic_union(std::in_place_index_t, Args&&... args) - noexcept(std::is_nothrow_constructible_v, std::in_place_index_t, Args...>) + noexcept(std::is_nothrow_constructible_v) : rest(std::in_place_index, std::forward(args)...) {} @@ -189,7 +215,9 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END template struct variadic_union { +#if IRIS_CI static_assert(!std::conjunction_v, std::is_trivially_destructible...>); +#endif static constexpr std::size_t size = sizeof...(Ts) + 1; static constexpr bool never_valueless = is_never_valueless_v; @@ -222,9 +250,11 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END template - requires (I != 0) && std::is_constructible_v, std::in_place_index_t, Args...> + requires + (I > 0) && (I < size) && + std::is_constructible_v constexpr explicit variadic_union(std::in_place_index_t, Args&&... args) - noexcept(std::is_nothrow_constructible_v, std::in_place_index_t, Args...>) + noexcept(std::is_nothrow_constructible_v) : rest(std::in_place_index, std::forward(args)...) {} diff --git a/include/iris/rvariant/detail/visit.hpp b/include/iris/rvariant/detail/visit.hpp index 3aaa36a..41a2f38 100644 --- a/include/iris/rvariant/detail/visit.hpp +++ b/include/iris/rvariant/detail/visit.hpp @@ -186,6 +186,14 @@ struct raw_visit_dispatch return static_cast(vis)(std::in_place_index<(n)>, detail::raw_get<(n)>(static_cast(storage))); \ } else std::unreachable(); [[fallthrough]] +#if IRIS_CI +# define IRIS_RAW_VISIT_ASSERT(flag_flip, strategy) \ + static_assert(flag_flip std::remove_cvref_t::never_valueless); \ + static_assert((1uz << ((strategy) * 2uz)) <= N && N <= (1uz << (((strategy) + 1) * 2uz))); +#else +# define IRIS_RAW_VISIT_ASSERT(flag_flip, strategy) +#endif + #define IRIS_RAW_VISIT_DISPATCH_DEF(strategy) \ template<> \ struct raw_visit_dispatch \ @@ -195,8 +203,7 @@ struct raw_visit_dispatch apply(std::size_t const i, [[maybe_unused]] Visitor&& vis, [[maybe_unused]] Storage&& storage) \ noexcept(detail::raw_visit_noexcept_all) \ { \ - static_assert(std::remove_cvref_t::never_valueless); \ - static_assert((1uz << ((strategy) * 2uz)) <= N && N <= (1uz << (((strategy) + 1) * 2uz))); \ + IRIS_RAW_VISIT_ASSERT(!!, strategy) \ switch (i) { \ IRIS_VISIT_CASES_ ## strategy (IRIS_RAW_VISIT_NEVER_VALUELESS_CASE, 0); \ default: std::unreachable(); \ @@ -211,8 +218,7 @@ struct raw_visit_dispatch apply(std::size_t const i, [[maybe_unused]] Visitor&& vis, [[maybe_unused]] Storage&& storage) \ noexcept(detail::raw_visit_noexcept_all) \ { \ - static_assert(!std::remove_cvref_t::never_valueless); \ - static_assert((1uz << ((strategy) * 2uz)) <= N && N <= (1uz << (((strategy) + 1) * 2uz))); \ + IRIS_RAW_VISIT_ASSERT(!, strategy) \ switch (i) { \ case 0: return static_cast(vis)(std::in_place_index, static_cast(storage)); \ IRIS_VISIT_CASES_ ## strategy (IRIS_RAW_VISIT_MAYBE_VALUELESS_CASE, 0); \ @@ -229,7 +235,7 @@ IRIS_RAW_VISIT_DISPATCH_DEF(3); #undef IRIS_RAW_VISIT_NEVER_VALUELESS_CASE #undef IRIS_RAW_VISIT_MAYBE_VALUELESS_CASE #undef IRIS_RAW_VISIT_DISPATCH_DEF - +#undef IRIS_RAW_VISIT_ASSERT template IRIS_FORCEINLINE constexpr raw_visit_result_t> @@ -461,6 +467,13 @@ struct visit_dispatch<-1> ); \ } else { std::unreachable(); } [[fallthrough]] +#if IRIS_CI +# define IRIS_VISIT_ASSERT(strategy) \ + static_assert((1uz << ((strategy) * 2uz)) <= OverloadSeq::size && OverloadSeq::size <= (1uz << (((strategy) + 1) * 2uz))); +#else +# define IRIS_VISIT_ASSERT(strategy) +#endif + #define IRIS_VISIT_DISPATCH_DEF(strategy) \ template<> \ struct visit_dispatch<(strategy)> \ @@ -469,7 +482,7 @@ struct visit_dispatch<-1> [[nodiscard]] static constexpr R apply(std::size_t const flat_i, [[maybe_unused]] Visitor&& vis, [[maybe_unused]] Storage&&... storage) \ noexcept(multi_visit_noexcept::value) \ { \ - static_assert((1uz << ((strategy) * 2uz)) <= OverloadSeq::size && OverloadSeq::size <= (1uz << (((strategy) + 1) * 2uz))); \ + IRIS_VISIT_ASSERT(strategy) \ switch (flat_i) { \ IRIS_VISIT_CASES_ ## strategy (IRIS_VISIT_CASE, 0); \ default: std::unreachable(); \ @@ -490,6 +503,8 @@ IRIS_VISIT_DISPATCH_DEF(3); #undef IRIS_VISIT_CASES_2 #undef IRIS_VISIT_CASES_3 +#undef IRIS_VISIT_ASSERT + template struct flat_index; diff --git a/include/iris/type_traits.hpp b/include/iris/type_traits.hpp index 2210a75..058d0dc 100644 --- a/include/iris/type_traits.hpp +++ b/include/iris/type_traits.hpp @@ -168,7 +168,8 @@ struct do_pack_indexing> { template static std::type_identity select( - decltype(void(Voids), static_cast(nullptr))..., + // ReSharper disable once CppCStyleCast + decltype((void*)Voids)..., std::type_identity*, ... ); @@ -182,7 +183,8 @@ struct do_cpack_indexing> { template static std::integral_constant select( - decltype(void(Voids), static_cast(nullptr))..., + // ReSharper disable once CppCStyleCast + decltype((void*)Voids)..., std::integral_constant*, ... ); diff --git a/test/core.cpp b/test/core.cpp index 30dd18d..c785453 100644 --- a/test/core.cpp +++ b/test/core.cpp @@ -372,11 +372,6 @@ TEST_CASE("Cpp17CopyAssignable") } } -template -concept Cpp17Destructible_expr = requires(T a) { - a.~T(); -}; - TEST_CASE("Cpp17Destructible") { STATIC_REQUIRE(iris::req::Cpp17Destructible);