Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -195,7 +197,7 @@ if(MSVC)
target_compile_options(
_iris_cxx_best_practices
INTERFACE
/W4 /analyze /analyze:external-
/W4
$<$<CONFIG:Release>:/Zi /Zo>
)
target_link_options(
Expand Down
72 changes: 51 additions & 21 deletions include/iris/rvariant/detail/variant_storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
// IWYU pragma: private, include <iris/rvariant.hpp>

#include <iris/rvariant/detail/rvariant_fwd.hpp>
#include <iris/rvariant/variant_helper.hpp>

#include <iris/type_traits.hpp>

#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -101,22 +102,41 @@ template<class Variant, class T>
// Additional size limit
inline constexpr std::size_t never_valueless_trivial_size_limit = 256;

template<class T>
concept is_never_valueless_impl =
is_ttp_specialization_of_v<T, recursive_wrapper> ||
(
sizeof(T) <= never_valueless_trivial_size_limit &&
std::is_trivially_destructible_v<T> &&
(
std::is_trivially_move_constructible_v<T> ||
std::is_trivially_copy_constructible_v<T>
) &&
(
std::is_trivially_move_assignable_v<T> ||
std::is_trivially_copy_assignable_v<T>
)
);

template<class... Ts>
struct is_never_valueless
: std::conjunction<
std::disjunction<
is_ttp_specialization_of<Ts, recursive_wrapper>,
std::conjunction<
std::bool_constant<sizeof(Ts) <= never_valueless_trivial_size_limit>,
std::is_trivially_destructible<Ts>,
std::disjunction<std::is_trivially_move_constructible<Ts>, std::is_trivially_copy_constructible<Ts>>,
std::disjunction<std::is_trivially_move_assignable<Ts>, std::is_trivially_copy_assignable<Ts>>
>
>...
struct is_never_valueless;

template<>
struct is_never_valueless<> : std::true_type {};

template<class T, class... Ts>
requires is_never_valueless_impl<T>
struct is_never_valueless<T, Ts...>
: std::bool_constant<
is_never_valueless<Ts...>::value
>
{
static_assert(sizeof...(Ts) > 0);
};
{};

template<class T, class... Ts>
requires (!is_never_valueless_impl<T>)
struct is_never_valueless<T, Ts...>
: std::false_type
{};

template<class... Ts>
constexpr bool is_never_valueless_v = is_never_valueless<Ts...>::value;
Expand All @@ -131,13 +151,17 @@ template<bool TriviallyDestructible, class... Ts>
struct variadic_union {};

template<class... Ts>
using make_variadic_union_t = variadic_union<std::conjunction_v<std::is_trivially_destructible<Ts>...>, Ts...>;

using make_variadic_union_t = variadic_union<
(std::is_trivially_destructible_v<Ts> && ...),
Ts...
>;

template<class T, class... Ts>
struct variadic_union<true, T, Ts...>
{
#if IRIS_CI
static_assert(std::conjunction_v<std::is_trivially_destructible<T>, std::is_trivially_destructible<Ts>...>);
#endif

static constexpr std::size_t size = sizeof...(Ts) + 1;
static constexpr bool never_valueless = is_never_valueless_v<T, Ts...>;
Expand Down Expand Up @@ -174,9 +198,11 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN
IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END

template<std::size_t I, class... Args>
requires (I != 0) && std::is_constructible_v<make_variadic_union_t<Ts...>, std::in_place_index_t<I - 1>, Args...>
requires
(I > 0) && (I < size) &&
std::is_constructible_v<IRIS_PACK_INDEXING(I - 1, Ts...), Args...>
constexpr explicit variadic_union(std::in_place_index_t<I>, Args&&... args)
noexcept(std::is_nothrow_constructible_v<make_variadic_union_t<Ts...>, std::in_place_index_t<I - 1>, Args...>)
noexcept(std::is_nothrow_constructible_v<IRIS_PACK_INDEXING(I - 1, Ts...), Args...>)
: rest(std::in_place_index<I - 1>, std::forward<Args>(args)...)
{}

Expand All @@ -189,7 +215,9 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END
template<class T, class... Ts>
struct variadic_union<false, T, Ts...>
{
#if IRIS_CI
static_assert(!std::conjunction_v<std::is_trivially_destructible<T>, std::is_trivially_destructible<Ts>...>);
#endif

static constexpr std::size_t size = sizeof...(Ts) + 1;
static constexpr bool never_valueless = is_never_valueless_v<T, Ts...>;
Expand Down Expand Up @@ -222,9 +250,11 @@ IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_BEGIN
IRIS_RVARIANT_ALWAYS_THROWING_UNREACHABLE_END

template<std::size_t I, class... Args>
requires (I != 0) && std::is_constructible_v<make_variadic_union_t<Ts...>, std::in_place_index_t<I - 1>, Args...>
requires
(I > 0) && (I < size) &&
std::is_constructible_v<IRIS_PACK_INDEXING(I - 1, Ts...), Args...>
constexpr explicit variadic_union(std::in_place_index_t<I>, Args&&... args)
noexcept(std::is_nothrow_constructible_v<make_variadic_union_t<Ts...>, std::in_place_index_t<I - 1>, Args...>)
noexcept(std::is_nothrow_constructible_v<IRIS_PACK_INDEXING(I - 1, Ts...), Args...>)
: rest(std::in_place_index<I - 1>, std::forward<Args>(args)...)
{}

Expand Down
27 changes: 21 additions & 6 deletions include/iris/rvariant/detail/visit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ struct raw_visit_dispatch<NeverValueless, -1>
return static_cast<Visitor&&>(vis)(std::in_place_index<(n)>, detail::raw_get<(n)>(static_cast<Storage&&>(storage))); \
} else std::unreachable(); [[fallthrough]]

#if IRIS_CI
# define IRIS_RAW_VISIT_ASSERT(flag_flip, strategy) \
static_assert(flag_flip std::remove_cvref_t<Storage>::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<true, (strategy)> \
Expand All @@ -195,8 +203,7 @@ struct raw_visit_dispatch<NeverValueless, -1>
apply(std::size_t const i, [[maybe_unused]] Visitor&& vis, [[maybe_unused]] Storage&& storage) \
noexcept(detail::raw_visit_noexcept_all<Visitor, Storage>) \
{ \
static_assert(std::remove_cvref_t<Storage>::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(); \
Expand All @@ -211,8 +218,7 @@ struct raw_visit_dispatch<NeverValueless, -1>
apply(std::size_t const i, [[maybe_unused]] Visitor&& vis, [[maybe_unused]] Storage&& storage) \
noexcept(detail::raw_visit_noexcept_all<Visitor, Storage>) \
{ \
static_assert(!std::remove_cvref_t<Storage>::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<Visitor&&>(vis)(std::in_place_index<std::variant_npos>, static_cast<Storage&&>(storage)); \
IRIS_VISIT_CASES_ ## strategy (IRIS_RAW_VISIT_MAYBE_VALUELESS_CASE, 0); \
Expand All @@ -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<class Variant, class Visitor>
IRIS_FORCEINLINE constexpr raw_visit_result_t<Visitor, forward_storage_t<Variant>>
Expand Down Expand Up @@ -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)> \
Expand All @@ -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<R, OverloadSeq, Visitor, Storage...>::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(); \
Expand All @@ -490,6 +503,8 @@ IRIS_VISIT_DISPATCH_DEF(3);
#undef IRIS_VISIT_CASES_2
#undef IRIS_VISIT_CASES_3

#undef IRIS_VISIT_ASSERT


template<class Ns, bool... NeverValueless>
struct flat_index;
Expand Down
6 changes: 4 additions & 2 deletions include/iris/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ struct do_pack_indexing<std::index_sequence<Voids...>>
{
template<class T>
static std::type_identity<T> select(
decltype(void(Voids), static_cast<void*>(nullptr))...,
// ReSharper disable once CppCStyleCast
decltype((void*)Voids)...,
std::type_identity<T>*,
...
);
Expand All @@ -182,7 +183,8 @@ struct do_cpack_indexing<std::index_sequence<Voids...>>
{
template<class T, T N>
static std::integral_constant<T, N> select(
decltype(void(Voids), static_cast<void*>(nullptr))...,
// ReSharper disable once CppCStyleCast
decltype((void*)Voids)...,
std::integral_constant<T, N>*,
...
);
Expand Down
5 changes: 0 additions & 5 deletions test/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,6 @@ TEST_CASE("Cpp17CopyAssignable")
}
}

template<class T>
concept Cpp17Destructible_expr = requires(T a) {
a.~T();
};

TEST_CASE("Cpp17Destructible")
{
STATIC_REQUIRE(iris::req::Cpp17Destructible<int>);
Expand Down
Loading