From 6e78025a464e43636fe7f359fef429943c3bccb1 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Thu, 20 Aug 2026 23:17:39 +0900 Subject: [PATCH 1/3] Make alloy first class citizen of Iris --- .gitignore | 1 + CMakeLists.txt | 30 +- include/iris/alloy/adapt.hpp | 41 ++ include/iris/alloy/adapted/std_pair.hpp | 34 ++ include/iris/alloy/adapted/std_tuple.hpp | 52 ++ include/iris/alloy/detail/deduce.hpp | 46 ++ .../alloy/detail/integer_seq_transform.hpp | 32 ++ .../alloy/detail/preprocessed/.clang-format | 16 + .../preprocessed/tuple_impl.hpp.post.in | 2 + .../detail/preprocessed/tuple_impl.hpp.pre.in | 23 + .../iris/alloy/detail/tuple_comparison.hpp | 68 +++ include/iris/alloy/detail/tuple_impl.hpp | 522 +++++++++++++++++ include/iris/alloy/io.hpp | 53 ++ include/iris/alloy/traits.hpp | 216 +++++++ include/iris/alloy/tuple.hpp | 412 ++++++++++++++ include/iris/alloy/utility.hpp | 333 +++++++++++ scripts/generate_natvis.py | 32 ++ scripts/generate_tuple_members.bat | 13 + scripts/generate_tuple_members.sh | 11 + test/CMakeLists.txt | 1 + test/alloy.cpp | 528 ++++++++++++++++++ test/iris_test.hpp | 2 +- 22 files changed, 2463 insertions(+), 5 deletions(-) create mode 100644 include/iris/alloy/adapt.hpp create mode 100644 include/iris/alloy/adapted/std_pair.hpp create mode 100644 include/iris/alloy/adapted/std_tuple.hpp create mode 100644 include/iris/alloy/detail/deduce.hpp create mode 100644 include/iris/alloy/detail/integer_seq_transform.hpp create mode 100644 include/iris/alloy/detail/preprocessed/.clang-format create mode 100644 include/iris/alloy/detail/preprocessed/tuple_impl.hpp.post.in create mode 100644 include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in create mode 100644 include/iris/alloy/detail/tuple_comparison.hpp create mode 100644 include/iris/alloy/detail/tuple_impl.hpp create mode 100644 include/iris/alloy/io.hpp create mode 100644 include/iris/alloy/traits.hpp create mode 100644 include/iris/alloy/tuple.hpp create mode 100644 include/iris/alloy/utility.hpp create mode 100644 scripts/generate_natvis.py create mode 100644 scripts/generate_tuple_members.bat create mode 100644 scripts/generate_tuple_members.sh create mode 100644 test/alloy.cpp diff --git a/.gitignore b/.gitignore index 43220b8..7f371c4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .DS_Store /build*/ +include/iris/alloy/detail/preprocessed/tuple_impl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ab03ec..a1c75a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,20 +214,42 @@ endif() # ----------------------------------------------------------------- # Configure Iris main target +option(IRIS_CI "Enables intensive testing for CI" OFF) +if(IRIS_CI) + target_compile_definitions(iris INTERFACE IRIS_CI=1) +endif() + file( GLOB_RECURSE IRIS_HEADERS ${PROJECT_SOURCE_DIR}/include/iris/*.hpp ${PROJECT_SOURCE_DIR}/include/iris/*.ipp ) +if(MSVC) + add_custom_command( + OUTPUT ${PROJECT_SOURCE_DIR}/include/iris/alloy/detail/preprocessed/tuple_impl.hpp + COMMAND ${PROJECT_SOURCE_DIR}/scripts/generate_tuple_members.bat + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/include/iris/alloy/detail/tuple_impl.hpp + VERBATIM + ) +else() + add_custom_command( + OUTPUT ${PROJECT_SOURCE_DIR}/include/iris/alloy/detail/preprocessed/tuple_impl.hpp + COMMAND ${PROJECT_SOURCE_DIR}/scripts/generate_tuple_members.sh + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/include/iris/alloy/detail/tuple_impl.hpp + VERBATIM + ) +endif() + +list(APPEND IRIS_HEADERS ${PROJECT_SOURCE_DIR}/include/iris/alloy/detail/preprocessed/tuple_impl.hpp) +list(REMOVE_DUPLICATES IRIS_HEADERS) + target_sources(iris PRIVATE FILE_SET HEADERS TYPE HEADERS FILES ${IRIS_HEADERS}) source_group(TREE ${PROJECT_SOURCE_DIR}/include/iris PREFIX iris FILES ${IRIS_HEADERS}) target_include_directories(iris INTERFACE ${PROJECT_SOURCE_DIR}/include) -option(IRIS_CI "Enables intensive testing for CI" OFF) -if(IRIS_CI) - target_compile_definitions(iris INTERFACE IRIS_CI=1) -endif() # ----------------------------------------------------------------- # Test diff --git a/include/iris/alloy/adapt.hpp b/include/iris/alloy/adapt.hpp new file mode 100644 index 0000000..89399fa --- /dev/null +++ b/include/iris/alloy/adapt.hpp @@ -0,0 +1,41 @@ +#ifndef IRIS_ZZ_ALLOY_ADAPT_HPP +#define IRIS_ZZ_ALLOY_ADAPT_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#include +#include + +namespace iris::alloy { + +namespace detail { + +template +struct non_type_list; + +} // detail + +template +struct adaptor; + +template +using make_getters_list = detail::non_type_list; + +} // iris::alloy + +#define IRIS_ALLOY_ADAPT_STRUCT(class_name, ...) \ + template<> \ + struct iris::alloy::adaptor { \ + using getters_list = make_getters_list; \ + }; + +#define IRIS_ALLOY_ADAPT_STRUCT_I(index, data_member, class_name) IRIS_PP_COMMA_IF(index) & class_name::data_member + +#endif diff --git a/include/iris/alloy/adapted/std_pair.hpp b/include/iris/alloy/adapted/std_pair.hpp new file mode 100644 index 0000000..0f260a8 --- /dev/null +++ b/include/iris/alloy/adapted/std_pair.hpp @@ -0,0 +1,34 @@ +#ifndef IRIS_ZZ_ALLOY_ADAPTED_STD_PAIR_HPP +#define IRIS_ZZ_ALLOY_ADAPTED_STD_PAIR_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +namespace iris::alloy { + +namespace detail { + +template +struct non_type_list; + +} // detail + +template +struct adaptor; + +template +struct adaptor> +{ + using getters_list = detail::non_type_list<&std::pair::first, &std::pair::second>; +}; + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/adapted/std_tuple.hpp b/include/iris/alloy/adapted/std_tuple.hpp new file mode 100644 index 0000000..49a0b1f --- /dev/null +++ b/include/iris/alloy/adapted/std_tuple.hpp @@ -0,0 +1,52 @@ +#ifndef IRIS_ZZ_ALLOY_ADAPTED_STD_TUPLE_HPP +#define IRIS_ZZ_ALLOY_ADAPTED_STD_TUPLE_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +#include +#include + +#include + +namespace iris::alloy { + +template +struct adaptor; + +namespace detail { + +template +struct call_std_get +{ + template + static constexpr decltype(auto) operator()(Tuple&& t) + { + return std::get(static_cast(t)); + } +}; + +template +struct make_call_std_get +{ + static constexpr auto value = call_std_get{}; +}; + +} // detail + +template +struct adaptor> +{ + using getters_list = detail::integer_seq_transform_t, detail::make_call_std_get>; +}; + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/detail/deduce.hpp b/include/iris/alloy/detail/deduce.hpp new file mode 100644 index 0000000..0f095c5 --- /dev/null +++ b/include/iris/alloy/detail/deduce.hpp @@ -0,0 +1,46 @@ +#ifndef IRIS_ZZ_ALLOY_DETAIL_DEDUCE_HPP +#define IRIS_ZZ_ALLOY_DETAIL_DEDUCE_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +namespace iris::alloy::detail { + +template +struct deduce +{ + static_assert(std::conjunction_v, std::is_reference, + std::is_same, std::remove_reference_t>>); +}; + +template +struct deduce +{ + using type = T&; +}; + +template +struct deduce +{ + using type = T; +}; + +template +struct deduce +{ + using type = T; +}; + +template +using deduce_t = typename deduce::type; + +} // iris::alloy::detail + +#endif diff --git a/include/iris/alloy/detail/integer_seq_transform.hpp b/include/iris/alloy/detail/integer_seq_transform.hpp new file mode 100644 index 0000000..02ac93e --- /dev/null +++ b/include/iris/alloy/detail/integer_seq_transform.hpp @@ -0,0 +1,32 @@ +#ifndef IRIS_ZZ_ALLOY_DETAIL_INTEGER_SEQ_TRANSFORM_HPP +#define IRIS_ZZ_ALLOY_DETAIL_INTEGER_SEQ_TRANSFORM_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +namespace iris::alloy::detail { + +template +struct non_type_list; + +template class F> +struct integer_seq_transform; + +template class F> +struct integer_seq_transform, F> +{ + using type = detail::non_type_list::value...>; +}; + +template class F> +using integer_seq_transform_t = typename integer_seq_transform::type; + +} // iris::alloy::detail + +#endif diff --git a/include/iris/alloy/detail/preprocessed/.clang-format b/include/iris/alloy/detail/preprocessed/.clang-format new file mode 100644 index 0000000..066b8bf --- /dev/null +++ b/include/iris/alloy/detail/preprocessed/.clang-format @@ -0,0 +1,16 @@ +AccessModifierOffset: -4 +AllowBreakBeforeNoexceptSpecifier: OnlyWithParen +AlwaysBreakTemplateDeclarations : true +ColumnLimit: 160 +FixNamespaceComments: false +IndentWidth: 4 +NamespaceIndentation: None +PointerAlignment: Left +QualifierAlignment: Right +UseTab: Never +AlignEscapedNewlines: DontAlign +BreakBeforeBraces: Mozilla +SpaceAfterTemplateKeyword: false +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterRequiresInClause: true diff --git a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.post.in b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.post.in new file mode 100644 index 0000000..ddd5dae --- /dev/null +++ b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.post.in @@ -0,0 +1,2 @@ + +#endif diff --git a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in new file mode 100644 index 0000000..bea50f6 --- /dev/null +++ b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in @@ -0,0 +1,23 @@ +#ifndef IRIS_ZZ_ALLOY_DETAIL_PREPROCESSED_TUPLE_IMPL_HPP +#define IRIS_ZZ_ALLOY_DETAIL_PREPROCESSED_TUPLE_IMPL_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +#include + +#include + +#include + +#include + +#include + diff --git a/include/iris/alloy/detail/tuple_comparison.hpp b/include/iris/alloy/detail/tuple_comparison.hpp new file mode 100644 index 0000000..fcbd69c --- /dev/null +++ b/include/iris/alloy/detail/tuple_comparison.hpp @@ -0,0 +1,68 @@ +#ifndef IRIS_ZZ_ALLOY_DETAIL_TUPLE_COMPARISON_HPP +#define IRIS_ZZ_ALLOY_DETAIL_TUPLE_COMPARISON_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +#include +#include + +namespace iris::alloy { + +template +class tuple; + +namespace detail { + +namespace equality_operator_poison_barrier { + +bool operator==(auto, auto) = delete; // poison-pill + +template +concept has_equality_operator = requires(T&& x, U&& y) { + { static_cast(x) == static_cast(y) } -> req::boolean_testable; +}; + +template +struct is_nothrow_equality_comparable : std::bool_constant && noexcept(std::declval() == std::declval())> {}; + +} // equality_operator_poison_barrier + +using equality_operator_poison_barrier::has_equality_operator; +using equality_operator_poison_barrier::is_nothrow_equality_comparable; + +template +struct do_tuple_all_elements_have_equality_operator {}; + +template +struct do_tuple_all_elements_have_equality_operator, tuple> + : std::bool_constant<(has_equality_operator && ...)> {}; + +template +inline constexpr bool do_tuple_all_elements_have_equality_operator_v = do_tuple_all_elements_have_equality_operator::value; + +template +concept tuple_all_elements_have_equality_operator = do_tuple_all_elements_have_equality_operator_v; + +template +struct are_tuple_all_elements_nothrow_equality_comparable {}; + +template +struct are_tuple_all_elements_nothrow_equality_comparable, tuple> + : std::conjunction...> {}; + +template +inline constexpr bool are_tuple_all_elements_nothrow_equality_comparable_v = are_tuple_all_elements_nothrow_equality_comparable::value; + +} // detail + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/detail/tuple_impl.hpp b/include/iris/alloy/detail/tuple_impl.hpp new file mode 100644 index 0000000..547714a --- /dev/null +++ b/include/iris/alloy/detail/tuple_impl.hpp @@ -0,0 +1,522 @@ +#ifndef IRIS_ZZ_ALLOY_DETAIL_TUPLE_IMPL_HPP +#define IRIS_ZZ_ALLOY_DETAIL_TUPLE_IMPL_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#ifndef IRIS_ALLOY_GENERATE_PREPROCESSED + +#include + +#include + +#include + +#include + +#include + +#include + +#endif + +#include +#include +#include +#include + +#define IRIS_ALLOY_EXPR_IF(cond, expr) IRIS_PP_IF(cond, expr, ) + +namespace iris::alloy { + +template +class tuple; + +template + requires detail::tuple_all_elements_have_equality_operator, tuple> +constexpr bool operator==(tuple const&, tuple const&) + noexcept(detail::are_tuple_all_elements_nothrow_equality_comparable_v, tuple>); + +namespace detail { + +template +class tuple_impl; + +template<> +class tuple_impl<> +{ + template + requires tuple_all_elements_have_equality_operator, tuple> + friend constexpr bool alloy::operator==(tuple const& a, tuple const& b) + noexcept(detail::are_tuple_all_elements_nothrow_equality_comparable_v, tuple>); + +private: + constexpr bool equal_to(tuple_impl const&) const noexcept { return true; } + +public: + tuple_impl() = default; + + tuple_impl(tuple_impl const&) = default; + + tuple_impl(tuple_impl&&) = default; + + constexpr tuple_impl(value_initialize_t) noexcept {} +}; + +#define IRIS_ALLOY_TUPLE_LIMIT 32 + +#define IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1 T +#define IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_2 U +#define IRIS_ALLOY_DETAIL_FUNCTION_PARAM_1 t +#define IRIS_ALLOY_DETAIL_FUNCTION_PARAM_2 u +#define IRIS_ALLOY_DETAIL_MEMBER_PREFIX _ + +#define IRIS_ALLOY_DETAIL_TEMPLATE_PARAMS(n, name) IRIS_PP_COMMA_IF(n) class IRIS_PP_CAT(name, n) +#define IRIS_ALLOY_DETAIL_ARGS(n, name) IRIS_PP_COMMA_IF(n) IRIS_PP_CAT(name, n) + +#define IRIS_ALLOY_DETAIL_MEM_DEFS(n, data) \ + IRIS_NO_UNIQUE_ADDRESS IRIS_PP_CAT(IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1, n) IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n); + +#define IRIS_ALLOY_DETAIL_FWD_PARAMS(n, data) \ + IRIS_PP_COMMA_IF(n) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_2, n) && IRIS_PP_CAT(IRIS_ALLOY_DETAIL_FUNCTION_PARAM_2, n) + +#define IRIS_ALLOY_DETAIL_FWD_INITS(n, data) \ + IRIS_PP_COMMA_IF(n) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, \ + n)(static_cast(IRIS_PP_CAT(IRIS_ALLOY_DETAIL_FUNCTION_PARAM_2, n))) + +#define IRIS_ALLOY_DETAIL_INITS(n, other) \ + IRIS_PP_COMMA_IF(n) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n)(other.IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n)) + +#define IRIS_ALLOY_DETAIL_NOTHROW_DEFAULT_CONSTRUCTIBLE(n, data) \ + IRIS_PP_COMMA_IF(n) std::is_nothrow_default_constructible + +#define IRIS_ALLOY_DETAIL_NOTHROW_CONSTRUCTIBLE(n, suffix) \ + IRIS_PP_COMMA_IF(n) \ + std::is_nothrow_constructible + +#define IRIS_ALLOY_DETAIL_NOTHROW_COPY_ASSIGNABLE(n, data) \ + IRIS_PP_COMMA_IF(n) std::is_nothrow_copy_assignable + +#define IRIS_ALLOY_DETAIL_NOTHROW_MOVE_ASSIGNABLE(n, data) \ + IRIS_PP_COMMA_IF(n) std::is_nothrow_move_assignable + +#define IRIS_ALLOY_DETAIL_NOTHROW_ASSIGNABLE(n, suffix) \ + IRIS_PP_COMMA_IF(n) \ + std::is_nothrow_assignable + +#define IRIS_ALLOY_DETAIL_VALUE_INITS(n, data) \ + IRIS_PP_COMMA_IF(n) IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) {} + +#define IRIS_ALLOY_DETAIL_ASSIGN(n, other) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) = other.IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n); + +#define IRIS_ALLOY_DETAIL_ASSIGN_ASSIGN(n, data) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) = \ + static_cast(IRIS_PP_CAT(IRIS_ALLOY_DETAIL_FUNCTION_PARAM_2, n)); + +#define IRIS_ALLOY_DETAIL_ASSIGN_GET(n, other) \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) = alloy::get(static_cast(other)); + +#define IRIS_ALLOY_DETAIL_SWAP(n, other) \ + swap(IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n), other.IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n)); + +#define IRIS_ALLOY_DETAIL_SWAPPABLE(n, data) IRIS_PP_COMMA_IF(n) std::is_swappable + +#define IRIS_ALLOY_DETAIL_NOTHROW_SWAPPABLE(n, data) \ + IRIS_PP_COMMA_IF(n) std::is_nothrow_swappable + +#define IRIS_ALLOY_DETAIL_LVALUE_GET(n, data) \ + IRIS_ALLOY_EXPR_IF(n, else) if constexpr (I == n) return IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n); + +#define IRIS_ALLOY_DETAIL_FORWARDING_GET(n, const_) \ + IRIS_ALLOY_EXPR_IF(n, else) \ + if constexpr (I == n) return static_cast( \ + IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n)); + +#define IRIS_ALLOY_DETAIL_EQUAL_TO(n, other) \ + IRIS_ALLOY_EXPR_IF(n, &&) IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) == other.IRIS_PP_CAT(IRIS_ALLOY_DETAIL_MEMBER_PREFIX, n) + +#define IRIS_ALLOY_DETAIL_NOTHROW_EQUALITY_COMPARABLE(n, data) \ + IRIS_PP_COMMA_IF(n) \ + is_nothrow_equality_comparable + +#define IRIS_ALLOY_DETAIL_TUPLE_IMPL_DEF(n, data) \ + template \ + class tuple_impl \ + { \ + template \ + friend class tuple_impl; \ +\ + template \ + requires tuple_all_elements_have_equality_operator, tuple> \ + friend constexpr bool alloy::operator==(tuple const&, tuple const&) \ + noexcept(detail::are_tuple_all_elements_nothrow_equality_comparable_v, tuple>); \ +\ + private: \ + template \ + constexpr bool equal_to(tuple_impl const& other) const \ + noexcept(std::conjunction_v) \ + { \ + return IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_EQUAL_TO, other); \ + } \ +\ + public: \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_MEM_DEFS, ) \ +\ + explicit tuple_impl() = default; \ +\ + explicit tuple_impl(tuple_impl const&) = default; \ +\ + explicit tuple_impl(tuple_impl&&) = default; \ +\ + constexpr explicit tuple_impl(value_initialize_t) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_VALUE_INITS, ) \ + { \ + } \ +\ + template \ + constexpr explicit tuple_impl(IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_FWD_PARAMS, )) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_FWD_INITS, ) \ + { \ + } \ +\ + template \ + constexpr explicit tuple_impl(tuple_impl& other) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_INITS, other) \ + { \ + } \ +\ + template \ + constexpr explicit tuple_impl(tuple_impl const& other) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_INITS, other) \ + { \ + } \ +\ + template \ + constexpr explicit tuple_impl(tuple_impl&& other) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_INITS, static_cast(other)) \ + { \ + } \ +\ + template \ + constexpr explicit tuple_impl( \ + tuple_impl const&& other) \ + noexcept(std::conjunction_v) \ + : IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_INITS, static_cast(other)) \ + { \ + } \ +\ + constexpr tuple_impl& operator=(tuple_impl const& other) \ + noexcept(std::conjunction_v) \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_ASSIGN, other) \ + return *this; \ + } \ +\ + constexpr tuple_impl& operator=(tuple_impl&& other) \ + noexcept(std::conjunction_v) \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_ASSIGN, static_cast(other)) \ + return *this; \ + } \ +\ + template \ + constexpr tuple_impl& \ + operator=(tuple_impl const& other) \ + noexcept(std::conjunction_v) \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_ASSIGN, other) \ + return *this; \ + } \ +\ + template \ + constexpr tuple_impl& operator=(tuple_impl&& other) \ + noexcept(std::conjunction_v) \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_ASSIGN, static_cast(other)) \ + return *this; \ + } \ +\ + template \ + constexpr tuple_impl& operator=(UTuple&& other) \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_ASSIGN_GET, other) \ + return *this; \ + } \ +\ + constexpr void swap(tuple_impl& other) noexcept(std::conjunction_v) \ + { \ + static_assert(std::conjunction_v); \ + using std::swap; \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_SWAP, other) \ + } \ +\ + template \ + constexpr pack_indexing_t& get() & noexcept \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_LVALUE_GET, ) \ + } \ +\ + template \ + constexpr pack_indexing_t const& \ + get() const& noexcept \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_LVALUE_GET, ) \ + } \ +\ + template \ + constexpr pack_indexing_t&& get() && noexcept \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_FORWARDING_GET, ) \ + } \ +\ + template \ + constexpr pack_indexing_t const&& \ + get() const&& noexcept \ + { \ + IRIS_PP_REPEAT(n, IRIS_ALLOY_DETAIL_FORWARDING_GET, const) \ + } \ + }; + +IRIS_PP_REPEAT_FROM_TO(1, IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_TUPLE_IMPL_DEF, ) + +template +class tuple_impl +{ + template + friend class tuple_impl; + + template + requires tuple_all_elements_have_equality_operator, tuple> + friend constexpr bool alloy::operator==(tuple const& a, tuple const& b) + noexcept(detail::are_tuple_all_elements_nothrow_equality_comparable_v, tuple>); + +private: + template + constexpr void assign(IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_FWD_PARAMS, ), Us&&... us) + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ASSIGN_ASSIGN, ) + rest.assign(static_cast(us)...); + } + + template + constexpr bool equal_to(tuple_impl const& other) const + noexcept(std::conjunction_v) \ + { + return IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_EQUAL_TO, other) && rest == other.rest; + } + +public: + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_MEM_DEFS, ) + IRIS_NO_UNIQUE_ADDRESS tuple_impl rest; + + explicit tuple_impl() = default; + + explicit tuple_impl(tuple_impl const&) = default; + + explicit tuple_impl(tuple_impl&&) = default; + + constexpr explicit tuple_impl(value_initialize_t vi) + noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_VALUE_INITS, ), rest(vi) + {} + + template + requires (sizeof...(Ts) == sizeof...(Us)) + constexpr explicit tuple_impl(IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_FWD_PARAMS, ), Us&&... us) + noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_FWD_INITS, ), rest(static_cast(us)...) + {} + + template + constexpr explicit tuple_impl( + tuple_impl& other) + noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_INITS, other), rest(other.rest) + {} + + template + constexpr explicit tuple_impl( + tuple_impl const& + other) noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_INITS, other), rest(other.rest) + {} + + template + constexpr explicit tuple_impl( + tuple_impl&& other) + noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_INITS, static_cast(other)), + rest(static_cast(other).rest) + {} + + template + constexpr explicit tuple_impl( + tuple_impl const&& + other) noexcept(std::conjunction_v...>) + : IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_INITS, static_cast(other)), + rest(static_cast(other).rest) + {} + + constexpr tuple_impl& operator=(tuple_impl const& other) + noexcept(std::conjunction_v...>) + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ASSIGN, other) + rest = other.rest; + return *this; + } + + constexpr tuple_impl& operator=(tuple_impl&& other) + noexcept(std::conjunction_v...>) + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ASSIGN, static_cast(other)) + rest = static_cast(other).rest; + return *this; + } + + template + constexpr tuple_impl& operator=( + tuple_impl const& other) + noexcept(std::conjunction_v...>) + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ASSIGN, other) + rest = other.rest; + return *this; + } + + template + constexpr tuple_impl& + operator=(tuple_impl&& other) + noexcept(std::conjunction_v...>) + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ASSIGN, static_cast(other)) + rest = static_cast(other).rest; + return *this; + } + + template + constexpr tuple_impl& operator=(UTuple&& other) + { + [&, this](std::index_sequence) { assign(alloy::get(static_cast(other))...); }(std::index_sequence_for{}); + return *this; + } + + constexpr void swap(tuple_impl& other) noexcept( + std::conjunction_v...>) + { + static_assert(std::conjunction_v...>); + using std::swap; + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_SWAP, other) + rest.swap(other.rest); + } + + template + constexpr pack_indexing_t< + I, + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ARGS, IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1), + Ts... + >& + get() & noexcept + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_LVALUE_GET, ) + else return rest.template get(); + } + + template + constexpr pack_indexing_t< + I, + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ARGS, IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1), + Ts... + > const& + get() const& noexcept + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_LVALUE_GET, ) + else return rest.template get(); + } + + template + constexpr pack_indexing_t< + I, + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ARGS, IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1), + Ts... + >&& + get() && noexcept + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_FORWARDING_GET, ) + else return std::move(rest).template get(); + } + + template + constexpr pack_indexing_t< + I, + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_ARGS, IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1), + Ts... + > const&& + get() const&& noexcept + { + IRIS_PP_REPEAT(IRIS_ALLOY_TUPLE_LIMIT, IRIS_ALLOY_DETAIL_FORWARDING_GET, const) + else return std::move(rest).template get(); + } +}; + +#undef IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_1 +#undef IRIS_ALLOY_DETAIL_TEMPLATE_PARAM_2 +#undef IRIS_ALLOY_DETAIL_FUNCTION_PARAM_1 +#undef IRIS_ALLOY_DETAIL_FUNCTION_PARAM_2 +#undef IRIS_ALLOY_DETAIL_MEMBER_PREFIX +#undef IRIS_ALLOY_DETAIL_TEMPLATE_PARAMS +#undef IRIS_ALLOY_DETAIL_ARGS +#undef IRIS_ALLOY_DETAIL_MEM_DEFS +#undef IRIS_ALLOY_DETAIL_FWD_PARAMS +#undef IRIS_ALLOY_DETAIL_FWD_INITS +#undef IRIS_ALLOY_DETAIL_INITS +#undef IRIS_ALLOY_DETAIL_ASSIGN +#undef IRIS_ALLOY_DETAIL_ASSIGN_GET +#undef IRIS_ALLOY_DETAIL_NOTHROW_DEFAULT_CONSTRUCTIBLE +#undef IRIS_ALLOY_DETAIL_NOTHROW_CONSTRUCTIBLE +#undef IRIS_ALLOY_DETAIL_NOTHROW_COPY_ASSIGNABLE +#undef IRIS_ALLOY_DETAIL_NOTHROW_MOVE_ASSIGNABLE +#undef IRIS_ALLOY_DETAIL_NOTHROW_ASSIGNABLE +#undef IRIS_ALLOY_DETAIL_VALUE_INITS +#undef IRIS_ALLOY_DETAIL_LVALUE_GET +#undef IRIS_ALLOY_DETAIL_TUPLE_IMPL_DEF + +} // detail + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/io.hpp b/include/iris/alloy/io.hpp new file mode 100644 index 0000000..675515e --- /dev/null +++ b/include/iris/alloy/io.hpp @@ -0,0 +1,53 @@ +#ifndef IRIS_ZZ_ALLOY_IO_HPP +#define IRIS_ZZ_ALLOY_IO_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +#include + +#include +#include + +#include + +namespace iris::alloy { + +namespace detail { + +template +struct tuple_ostream_impl; + +template +struct tuple_ostream_impl> +{ + template + static constexpr std::ostream& apply(std::ostream& os, tuple const& t) + { + os << '('; + [[maybe_unused]] bool first = true; + ((std::exchange(first, false) ? os << alloy::get(t) : os << ", " << alloy::get(t)), ...); + os << ')'; + return os; + } +}; + +} // detail + +template + requires std::conjunction_v...> +std::ostream& operator<<(std::ostream& os, tuple const& t) +{ + return detail::tuple_ostream_impl>::apply(os, t); +} + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/traits.hpp b/include/iris/alloy/traits.hpp new file mode 100644 index 0000000..1f1c2bf --- /dev/null +++ b/include/iris/alloy/traits.hpp @@ -0,0 +1,216 @@ +#ifndef IRIS_ZZ_ALLOY_COMMON_DEF_HPP +#define IRIS_ZZ_ALLOY_COMMON_DEF_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include + +#include + +#include +#include + +#include + +namespace iris::alloy { + +template +struct adaptor; + +namespace detail { + +template +struct non_type_list_size {}; + +template class TList, auto... Vs> +struct non_type_list_size> : std::integral_constant {}; + +template +struct non_type_list_indexing {}; + +template class TList, auto... Vs> +struct non_type_list_indexing> : cpack_indexing {}; + +} // detail + +struct value_initialize_t {}; + +inline constexpr value_initialize_t value_initialize{}; + +template +class tuple; + +template +struct adaptor; + +namespace detail { + +template +concept PureAdapted = requires { typename adaptor::getters_list; }; + +template +concept PureTupleLike = is_ttp_specialization_of_v || PureAdapted; + +} // detail + +template +struct is_tuple_like : std::bool_constant> {}; + +template +inline constexpr bool is_tuple_like_v = is_tuple_like::value; + +template +concept Adapted = detail::PureAdapted>; + +template +concept TupleLike = detail::PureTupleLike>; + +template +struct tuple_size {}; + +template +struct tuple_size : tuple_size {}; + +template +struct tuple_size> : std::integral_constant {}; + +template +struct tuple_size : detail::non_type_list_size::getters_list> {}; + +template +inline constexpr std::size_t tuple_size_v = tuple_size::value; + +template +struct tuple_element {}; + +template +struct tuple_element> +{ + using type = IRIS_CORE_PACK_INDEXING(I, Ts...); +}; + +template +using tuple_element_t = typename tuple_element::type; + +template +[[nodiscard]] constexpr tuple_element_t>& get(tuple& t) noexcept; + +template +[[nodiscard]] constexpr tuple_element_t> const& get(tuple const& t) noexcept; + +template +[[nodiscard]] constexpr tuple_element_t>&& get(tuple&& t) noexcept; + +template +[[nodiscard]] constexpr tuple_element_t> const&& get(tuple const&& t) noexcept; + +namespace detail { + +template +inline constexpr auto getter_of = non_type_list_indexing::getters_list>::value; + +} // namespace detail + +template +[[nodiscard]] constexpr auto get(T&& x) + noexcept(std::is_nothrow_invocable_v>), T>) + -> std::invoke_result_t>), T> +{ + return std::invoke(detail::getter_of>, std::forward(x)); +} + +namespace detail { + +template +using tuple_get_t = decltype(alloy::get(std::declval())); + +template +struct is_nothrow_gettable : std::bool_constant(std::declval()))> {}; + +template +inline constexpr bool is_nothrow_gettable_v = is_nothrow_gettable::value; + +} // detail + +template +struct tuple_element +{ + // Since we only have access through getters, we don't know exact types of user-defined tuple-like types' elements. + // Threrefore, we deduce the types from what we get from getters. + using type = detail::deduce_t&>&&, detail::tuple_get_t&&>&&>; +}; + +namespace detail { + +template +struct is_view_impl {}; + +template +struct is_view_impl> : std::conjunction>...> {}; + +template +struct is_view : std::false_type {}; + +template + requires is_tuple_like_v +struct is_view : is_view_impl>> {}; + +} // detail + +template +struct is_tuple_like_view : std::conjunction, detail::is_view> {}; + +template +concept TupleLikeView = TupleLike && detail::is_view>::value; + +template +inline constexpr bool is_tuple_like_view_v = is_tuple_like_view::value; + +namespace detail { + +template class TQual, template class UQual, class IndexSeq> +struct basic_common_reference_impl; + +template class TQual, template class UQual, std::size_t... Is> +struct basic_common_reference_impl> +{ + using type = tuple>, UQual>>...>; +}; + +} // detail + +} // iris::alloy + +// Note: We can't directly specify the concept `TupleLike` in the +// declaration of the template parameter because it would invoke +// the `TupleLike` check for virtually ANY types whenever the +// *primary* template of `std::basic_common_reference` is instantiated. +// +// Doing so would produce some hard errors on completely irrelevant +// context; for example, calling `std::map{}.rbegin()` would +// inevitably *check* `TupleLike` for `std::pair` thus +// leads to instantiation of `getter_of`. Then if the instantiation +// yields hard error for some reason, the error is propagated to the +// caller in SFINAE-unfriendly context. +template class TQual, template class UQual> + requires + ( + iris::is_ttp_specialization_of_v || + iris::is_ttp_specialization_of_v + ) && + iris::alloy::TupleLike && iris::alloy::TupleLike && + (iris::alloy::tuple_size_v == iris::alloy::tuple_size_v) +struct std::basic_common_reference + : iris::alloy::detail::basic_common_reference_impl< + TTuple, UTuple, TQual, UQual, + std::make_index_sequence> + > +{}; + +#endif diff --git a/include/iris/alloy/tuple.hpp b/include/iris/alloy/tuple.hpp new file mode 100644 index 0000000..5b21b72 --- /dev/null +++ b/include/iris/alloy/tuple.hpp @@ -0,0 +1,412 @@ +#ifndef IRIS_ZZ_ALLOY_TUPLE_HPP +#define IRIS_ZZ_ALLOY_TUPLE_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#ifndef IRIS_USE_PREPROCESSED +#define IRIS_USE_PREPROCESSED 1 +#endif + +#if IRIS_USE_PREPROCESSED +#include +#else +#include +#endif + +#include +#include + +#include +#include + +#include + +namespace iris::alloy { + +namespace detail { + +template +struct type_list; + +template +struct tuple_traits_impl; + +template +struct tuple_traits_impl, UTuple, Ts...> +{ + static constexpr bool all_convertible = std::conjunction_v, Ts>...>; + static constexpr bool all_constructible = std::conjunction_v>...>; + static constexpr bool all_nothrow_constructible = std::conjunction_v>...>; + static constexpr bool all_assignable = std::conjunction_v>...>; + static constexpr bool all_nothrow_assignable = std::conjunction_v>...>; + static constexpr bool all_nothrow_gettable = std::conjunction_v...>; +#if __cpp_lib_reference_from_temporary >= 202202L + static constexpr bool any_reference_constructs_from_temporary = std::disjunction_v>...>; +#endif +}; + +template +struct tuple_traits : tuple_traits_impl, UTuple, Ts...> {}; + +template +struct tuple_one_element_is_constructible_from_tuple + : std::bool_constant<(sizeof...(Ts) == 1) && + (std::is_convertible_v || std::is_constructible_v)> +{}; + +template +inline constexpr bool tuple_one_element_is_constructible_from_tuple_v = tuple_one_element_is_constructible_from_tuple::value; + +} // detail + +template +class tuple : public detail::tuple_impl +{ +private: + static_assert(!std::disjunction_v...>, "alloy::tuple must not be instantiated with rvalue reference type"); + using base_type = detail::tuple_impl; + + template + static constexpr bool disambiguating_constraint = []() { + if constexpr (sizeof...(Ts) == 1) { + return !std::is_same_v, tuple>; + } else { + return true; + } + }(); + + struct construct_t {}; + + static constexpr construct_t construct{}; + + template + constexpr explicit tuple(construct_t, std::index_sequence, UTuple&& other) + noexcept(detail::tuple_traits::all_nothrow_gettable && detail::tuple_traits::all_nothrow_constructible) + : base_type(alloy::get(static_cast(other))...) + {} + +public: + tuple() = default; + + tuple(tuple const&) = default; + + tuple(tuple&&) + requires std::conjunction_v...> + = default; + + constexpr explicit tuple(value_initialize_t vi) + noexcept(std::conjunction_v...>) + : base_type(vi) {} + + constexpr explicit(!std::conjunction_v...>) tuple(Ts const&... ts) + noexcept(std::conjunction_v...>) + requires requires { + requires (sizeof...(Ts) > 0); + requires std::conjunction_v...>; + } + : base_type(ts...) + {} + + template + requires requires { + requires (sizeof...(Ts) == sizeof...(Us)); + requires disambiguating_constraint; + requires std::conjunction_v...>; + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!(std::reference_constructs_from_temporary_v || ...)) +#endif + constexpr explicit(!std::conjunction_v...>) tuple(Us&&... us) + noexcept(std::conjunction_v...>) + : base_type(static_cast(us)...) + {} + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v&, Ts...>); + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!detail::tuple_traits&, Ts...>::any_reference_constructs_from_temporary) +#endif + constexpr explicit(!detail::tuple_traits&, Ts...>::all_convertible) tuple(tuple& other) + noexcept(detail::tuple_traits&, Ts...>::all_nothrow_constructible) + : base_type(static_cast&>(other)) + {} + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits const&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v const&, Ts...>); + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!detail::tuple_traits const&, Ts...>::any_reference_constructs_from_temporary) +#endif + constexpr explicit(!detail::tuple_traits const&, Ts...>::all_convertible) tuple(tuple const& other) + noexcept(detail::tuple_traits const&, Ts...>::all_nothrow_constructible) + : base_type(static_cast const&>(other)) + {} + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits&&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v&&, Ts...>); + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!detail::tuple_traits&&, Ts...>::any_reference_constructs_from_temporary) +#endif + constexpr explicit(!detail::tuple_traits&&, Ts...>::all_convertible) tuple(tuple&& other) + noexcept(detail::tuple_traits&&, Ts...>::all_nothrow_constructible) + : base_type(static_cast&&>(other)) + {} + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits const&&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v const&&, Ts...>); + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!detail::tuple_traits const&&, Ts...>::any_reference_constructs_from_temporary) +#endif + constexpr explicit(!detail::tuple_traits const&&, Ts...>::all_convertible) tuple(tuple const&& other) + noexcept(detail::tuple_traits const&&, Ts...>::all_nothrow_constructible) + : base_type(static_cast const&&>(other)) + {} + + template + requires requires { + requires !std::is_same_v, tuple>; + requires sizeof...(Ts) == tuple_size_v>; + requires detail::tuple_traits::all_constructible; + requires !detail::tuple_one_element_is_constructible_from_tuple_v; + } +#if __cpp_lib_reference_from_temporary >= 202202L + && (!detail::tuple_traits::any_reference_constructs_from_temporary) +#endif + constexpr explicit(!detail::tuple_traits::all_convertible) tuple(UTuple&& other) + noexcept(detail::tuple_traits::all_nothrow_gettable && detail::tuple_traits::all_nothrow_constructible) + : tuple(construct, std::make_index_sequence>>{}, static_cast(other)) + {} + +#if __cpp_lib_reference_from_temporary >= 202202L + template + requires requires { + requires (sizeof...(Ts) == sizeof...(Us)); + requires disambiguating_constraint; + requires std::conjunction_v...>; + } + && (std::reference_constructs_from_temporary_v || ...) + constexpr explicit(!std::conjunction_v...>) tuple(Us&&... us) + noexcept(std::conjunction_v...>) + = delete; + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v&, Ts...>); + } + && detail::tuple_traits&, Ts...>::any_reference_constructs_from_temporary + constexpr explicit(!detail::tuple_traits&, Ts...>::all_convertible) tuple(tuple& other) + noexcept(detail::tuple_traits&, Ts...>::all_nothrow_constructible) + = delete; + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits const&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v const&, Ts...>); + } + && detail::tuple_traits const&, Ts...>::any_reference_constructs_from_temporary + constexpr explicit(!detail::tuple_traits const&, Ts...>::all_convertible) tuple(tuple const& other) + noexcept(detail::tuple_traits const&, Ts...>::all_nothrow_constructible) + = delete; + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits&&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v&&, Ts...>); + } + && detail::tuple_traits&&, Ts...>::any_reference_constructs_from_temporary + constexpr explicit(!detail::tuple_traits&&, Ts...>::all_convertible) tuple(tuple&& other) + noexcept(detail::tuple_traits&&, Ts...>::all_nothrow_constructible) + = delete; + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires std::negation_v...>>; + requires detail::tuple_traits const&&, Ts...>::all_constructible; + requires (!detail::tuple_one_element_is_constructible_from_tuple_v const&&, Ts...>); + } + && detail::tuple_traits const&&, Ts...>::any_reference_constructs_from_temporary + constexpr explicit(!detail::tuple_traits const&&, Ts...>::all_convertible) tuple(tuple const&& other) + noexcept(detail::tuple_traits const&&, Ts...>::all_nothrow_constructible) + = delete; + + template + requires requires { + requires !std::is_same_v, tuple>; + requires sizeof...(Ts) == tuple_size_v>; + requires detail::tuple_traits::all_constructible; + requires !detail::tuple_one_element_is_constructible_from_tuple_v; + } + && detail::tuple_traits::any_reference_constructs_from_temporary + constexpr explicit(!detail::tuple_traits::all_convertible) tuple(UTuple&& other) + noexcept(detail::tuple_traits::all_nothrow_gettable && detail::tuple_traits::all_nothrow_constructible) + = delete; +#endif + + constexpr tuple& operator=(tuple const& other) + noexcept(std::conjunction_v...>) + { + base_type::operator=(other); + return *this; + + } + constexpr tuple& operator=(tuple&& other) + noexcept(std::conjunction_v...>) + requires std::conjunction_v...> + { + base_type::operator=(static_cast(other)); + return *this; + } + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires detail::tuple_traits const&, Ts...>::all_assignable; + } + constexpr tuple& operator=(tuple const& other) + noexcept(detail::tuple_traits const&, Ts...>::all_nothrow_assignable) + { + base_type::operator=(static_cast const&>(other)); + return *this; + } + + template + requires requires { + requires sizeof...(Ts) == sizeof...(Us); + requires detail::tuple_traits&&, Ts...>::all_assignable; + } + constexpr tuple& operator=(tuple&& other) + noexcept(detail::tuple_traits&&, Ts...>::all_nothrow_assignable) + { + base_type::operator=(static_cast &&>(other)); + return *this; + } + + template + requires requires { + requires !std::is_same_v, tuple>; + requires sizeof...(Ts) == tuple_size_v>; + requires detail::tuple_traits::all_assignable; + } + constexpr tuple& operator=(UTuple&& other) + noexcept(detail::tuple_traits::all_nothrow_assignable) + { + base_type::operator=(static_cast(other)); + return *this; + } + + constexpr void swap(tuple& other) noexcept(std::conjunction_v...>) + { + base_type::swap(other); + } + + template + [[nodiscard]] constexpr tuple_element_t& get() & noexcept + { + static_assert(I < sizeof...(Ts)); + return base_type::template get(); + } + + template + [[nodiscard]] constexpr tuple_element_t const& get() const& noexcept + { + static_assert(I < sizeof...(Ts)); + return base_type::template get(); + } + + template + [[nodiscard]] constexpr tuple_element_t&& get() && noexcept + { + static_assert(I < sizeof...(Ts)); + return std::move(*this).base_type::template get(); + } + + template + [[nodiscard]] constexpr tuple_element_t const&& get() const&& noexcept + { + static_assert(I < sizeof...(Ts)); + return std::move(*this).base_type::template get(); + } +}; + +template +tuple(Ts...) -> tuple; + +template + requires std::conjunction_v...> +constexpr void swap(tuple& a, tuple& b) noexcept(noexcept(a.swap(b))) +{ + a.swap(b); +} + +template + requires detail::tuple_all_elements_have_equality_operator, tuple> +constexpr bool operator==(tuple const& a, tuple const& b) + noexcept(detail::are_tuple_all_elements_nothrow_equality_comparable_v, tuple>) +{ + return a.equal_to(b); +} + +template +[[nodiscard]] constexpr tuple_element_t>& get(tuple& t) noexcept +{ + static_assert(I < sizeof...(Ts)); + return t.template get(); +} + +template +[[nodiscard]] constexpr tuple_element_t> const& get(tuple const& t) noexcept +{ + static_assert(I < sizeof...(Ts)); + return t.template get(); +} + +template +[[nodiscard]] constexpr tuple_element_t>&& get(tuple&& t) noexcept +{ + static_assert(I < sizeof...(Ts)); + return static_cast&&>(t).template get(); +} + +template +[[nodiscard]] constexpr tuple_element_t> const&& get(tuple const&& t) noexcept +{ + static_assert(I < sizeof...(Ts)); + return static_cast const&&>(t).template get(); +} + +} // iris::alloy + +#endif diff --git a/include/iris/alloy/utility.hpp b/include/iris/alloy/utility.hpp new file mode 100644 index 0000000..0f556a5 --- /dev/null +++ b/include/iris/alloy/utility.hpp @@ -0,0 +1,333 @@ +#ifndef IRIS_ZZ_ALLOY_UTILITY_HPP +#define IRIS_ZZ_ALLOY_UTILITY_HPP + +/*============================================================================= + Copyright (c) 2025 Yaito Kakeyama + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#include + +#include +#include +#include + +#include + +namespace iris::alloy { + +namespace detail { + +template +struct type_list; + +template +struct tuple_cat_result_impl; + +template +struct tuple_cat_result_impl, type_list<>> +{ + using type = tuple; +}; + +template +struct tuple_cat_result_impl, type_list, IndexSeqs...>, Tuple, Tuples...> + : tuple_cat_result_impl>...>, type_list, Tuples...> {}; + +template +struct tuple_cat_result : tuple_cat_result_impl, type_list>>...>, Tuples...> {}; + +template +struct tuple_cat_impl_base; + +template +struct tuple_cat_impl_base> +{ + template + static constexpr bool nothrow = std::is_nothrow_constructible_v; + + template + static constexpr ResultTuple apply(Args&&... args) noexcept(nothrow) + { + return ResultTuple(std::forward(args)...); + } +}; + +template +struct tuple_cat_impl_base, IndexSeqs...>, Tuple, Tuples...> +{ + template + static constexpr bool nothrow = + tuple_cat_impl_base, Tuples...>::template nothrow && (is_nothrow_gettable_v && ...); + + template + static constexpr ResultTuple apply(Tuple&& tuple, Tuples&&... tuples, Args&&... args) noexcept(nothrow) + { + return tuple_cat_impl_base, Tuples...>::apply(std::forward(tuples)..., std::forward(args)..., + alloy::get(std::forward(tuple))...); + } +}; + +template +struct tuple_cat_impl +{ + using Base = tuple_cat_impl_base::type, + detail::type_list>>...>, Tuples...>; + + static constexpr bool nothrow = Base::template nothrow<>; + + static constexpr typename tuple_cat_result::type apply(Tuples&&... tuples) noexcept(nothrow) + { + return Base::apply(std::forward(tuples)...); + } +}; + +template +struct index_sequence_split_impl; + +template + requires (sizeof...(Is) < N) +struct index_sequence_split_impl, std::index_sequence> + : index_sequence_split_impl, std::index_sequence> {}; + +template + requires (sizeof...(Is) == N) +struct index_sequence_split_impl, std::index_sequence> +{ + using head = std::index_sequence; + using tail = std::index_sequence; +}; + +template +struct index_sequence_split : index_sequence_split_impl, IndexSeq> {}; + +template +struct index_sequence_take +{ + using type = typename index_sequence_split::head; +}; + +template +using index_sequence_take_t = typename index_sequence_take::type; + +template +struct index_sequence_drop +{ + using type = typename index_sequence_split::tail; +}; + +template +using index_sequence_drop_t = typename index_sequence_drop::type; + +template +struct index_sequence_subrange +{ + using type = index_sequence_take_t>; +}; + +template +using index_sequence_subrange_t = typename index_sequence_subrange::type; + +template +struct index_sequence_sum; + +template +struct index_sequence_sum> : std::integral_constant {}; + +template +inline constexpr std::size_t index_sequence_sum_v = index_sequence_sum::value; + +template +struct index_sequence_cumulative_sum_impl; + +template +struct index_sequence_cumulative_sum_impl, ValIndexSeq> +{ + using type = std::index_sequence<0, index_sequence_sum_v>...>; +}; + +template +struct index_sequence_cumulative_sum; + +template +struct index_sequence_cumulative_sum> + : index_sequence_cumulative_sum_impl, std::index_sequence> {}; + +template +using index_sequence_cumulative_sum_t = typename index_sequence_cumulative_sum::type; + +template +struct index_sequence_segment_impl; + +template +struct index_sequence_segment_impl, std::index_sequence> +{ + using type = type_list...>; +}; + +template +struct index_sequence_segment; + +template +struct index_sequence_segment, Sizes...> +{ + using CumSumIndexSeq = index_sequence_cumulative_sum_t>; + + using type = typename index_sequence_segment_impl, index_sequence_take_t, + index_sequence_drop_t<1, CumSumIndexSeq>>::type; +}; + +template +using index_sequence_segment_t = typename index_sequence_segment::type; + +template +struct tuple_from_tuple_and_index_sequence; + +template +struct tuple_from_tuple_and_index_sequence> +{ + using type = tuple>...>; +}; + +template +using tuple_from_tuple_and_index_sequence_t = typename tuple_from_tuple_and_index_sequence::type; + +template +struct tuple_split_result_impl; + +template +struct tuple_split_result_impl> +{ + using type = tuple...>; +}; + +template +struct tuple_split_result +{ + using type = typename tuple_split_result_impl>>, Sizes...>>::type; +}; + +template +struct tuple_split_make_inner; + +template +struct tuple_split_make_inner> +{ + static constexpr bool nothrow = std::conjunction_v< + is_nothrow_gettable..., + std::is_nothrow_constructible...> + >; + + static constexpr ResultInnerTuple apply(Tuple&& t) noexcept(nothrow) + { + return ResultInnerTuple(alloy::get(std::forward(t))...); + } +}; + +template +struct tuple_split_make_outer; + +template +struct tuple_split_make_outer, Tuple, type_list> +{ + static constexpr bool nothrow = (tuple_split_make_inner::nothrow && ...); + + static constexpr tuple apply(Tuple&& t) noexcept(nothrow) + { + return tuple(tuple_split_make_inner::apply(std::forward(t))...); + } +}; + +template +struct tuple_split_impl : tuple_split_make_outer::type, Tuple, + index_sequence_segment_t>>, Sizes...>> {}; + +template>>> +struct tuple_assign_impl; + +template +struct tuple_assign_impl> +{ + static constexpr bool nothrow = std::conjunction_v, is_nothrow_gettable>..., + std::is_nothrow_assignable, tuple_get_t>...>; + + static constexpr void apply(From&& from, To&& to) noexcept(nothrow) + { + ((void)(alloy::get(std::forward(to)) = alloy::get(std::forward(from))), ...); + } +}; + +template +struct tuple_ref_result_impl; + +template +struct tuple_ref_result_impl> +{ + using type = tuple&...>; +}; + +template +struct tuple_ref_result : tuple_ref_result_impl>> {}; + +template +struct for_each_impl; + +template +struct for_each_impl> +{ + template + static constexpr void apply(Tuple&& t, F&& f){ + ((void)std::invoke(std::forward(f), alloy::get(std::forward(t))), ...); + } +}; + +} // detail + +template +using tuple_cat_t = typename detail::tuple_cat_result::type; + +template +using tuple_split_t = typename detail::tuple_split_result::type; + +template +using tuple_ref_t = typename detail::tuple_ref_result::type; + +template +[[nodiscard]] constexpr tuple_cat_t tuple_cat(Tuples&&... tuples) noexcept(detail::tuple_cat_impl::nothrow) +{ + return detail::tuple_cat_impl::apply(std::forward(tuples)...); +} + +template +[[nodiscard]] constexpr tuple_split_t tuple_split(Tuple&& t) noexcept(detail::tuple_split_impl::nothrow) +{ + static_assert((0 + ... + Sizes) == tuple_size_v>); + return detail::tuple_split_impl::apply(std::forward(t)); +} + +template +constexpr void tuple_assign(From&& from, To&& to) noexcept(detail::tuple_assign_impl::nothrow) +{ + static_assert(tuple_size_v> == tuple_size_v>); + detail::tuple_assign_impl::apply(std::forward(from), std::forward(to)); +} + +template +[[nodiscard]] constexpr tuple_ref_t tuple_ref(Tuple& t) noexcept(std::is_nothrow_constructible_v, Tuple&>) +{ + return tuple_ref_t(t); +} + +template +constexpr void for_each(Tuple&& t, F&& f) +{ + return detail::for_each_impl>>>::apply(std::forward(t), std::forward(f)); +} + +} // iris::alloy + +#endif diff --git a/scripts/generate_natvis.py b/scripts/generate_natvis.py new file mode 100644 index 0000000..29f4792 --- /dev/null +++ b/scripts/generate_natvis.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# Copyright 2026 The Iris Project Contributors +# +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +N = 32 + +print('') +print('') +print(' ') + +# DisplayString: 32 -> 1 +for k in range(N, 0, -1): + elems = ", ".join(f"{{_{i}}}" for i in range(k)) + print(f' ({elems})') + +print() +print(' ') + +# Expand: 0 -> 31 +for i in range(N): + print(f' _{i}') + +print(' ') +print(' ') +print('') diff --git a/scripts/generate_tuple_members.bat b/scripts/generate_tuple_members.bat new file mode 100644 index 0000000..2c53063 --- /dev/null +++ b/scripts/generate_tuple_members.bat @@ -0,0 +1,13 @@ +REM Copyright 2026 The Iris Project Contributors +REM +REM Distributed under the Boost Software License, Version 1.0. +REM https://www.boost.org/LICENSE_1_0.txt +@echo off +cl /TP /std:c++23preview /Iinclude /Imodules\boost_preprocessor\include /Imodules\iris\include /P /EP /C /DIRIS_ALLOY_GENERATE_PREPROCESSED /Fiinclude\iris\alloy\detail\preprocessed\temp.hpp include\iris\alloy\detail\tuple_impl.hpp +pushd include\iris\alloy\detail\preprocessed +type tuple_impl.hpp.pre.in temp.hpp tuple_impl.hpp.post.in > temp2.hpp +clang-format -i temp2.hpp +del /q tuple_impl.hpp +rename temp2.hpp tuple_impl.hpp +del temp.hpp +popd diff --git a/scripts/generate_tuple_members.sh b/scripts/generate_tuple_members.sh new file mode 100644 index 0000000..bba7fe5 --- /dev/null +++ b/scripts/generate_tuple_members.sh @@ -0,0 +1,11 @@ +#!/usr/bin/sh +# Copyright 2026 The Iris Project Contributors +# +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt +g++ -Iinclude -Imodules/boost_preprocessor/include -Imodules/iris/include -E -P -DIRIS_ALLOY_GENERATE_PREPROCESSED include/iris/alloy/detail/tuple_impl.hpp > include/iris/alloy/detail/preprocessed/temp.hpp +cd include/iris/alloy/detail/preprocessed +cat tuple_impl.hpp.pre.in temp.hpp tuple_impl.hpp.post.in > temp2.hpp +clang-format -i temp2.hpp +mv temp2.hpp tuple_impl.hpp +rm temp.hpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7ea03d5..2d4e6dd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -191,6 +191,7 @@ if(PROJECT_IS_TOP_LEVEL) interval_algo interval_set snippet + alloy ) foreach(test_name IN LISTS IRIS_TEST_IRIS_TESTS) iris_define_internal_test(${test_name} ${test_name}.cpp) diff --git a/test/alloy.cpp b/test/alloy.cpp new file mode 100644 index 0000000..65c4c94 --- /dev/null +++ b/test/alloy.cpp @@ -0,0 +1,528 @@ +/*============================================================================= + Copyright (c) 2026 The Iris Project Contributors + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#include "iris_test.hpp" + +#include + +#include +#include + +#include +#include +#include +#include + +namespace alloy = iris::alloy; + +struct NonAdaptedStruct +{}; + +struct AdaptedStruct +{ + int x; + double y; +}; + +IRIS_ALLOY_ADAPT_STRUCT(AdaptedStruct, x, y) + +struct OldStyle +{ + int i; + std::string str; + int get_int() const { return i; } + std::string const& get_string() const { return str; } +}; + +template<> +struct alloy::adaptor +{ + using getters_list = make_getters_list<&OldStyle::get_int, &OldStyle::get_string>; +}; + +template +using alloy_get_t = decltype(alloy::get(std::declval())); + +namespace { + +void swap() = delete; // poison-pill + +} + +TEST_CASE("adapt_struct") +{ + + { + STATIC_CHECK(!alloy::TupleLike); + } + + { + STATIC_CHECK(alloy::TupleLike); + + STATIC_CHECK(alloy::tuple_size_v == 2); + + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int&&>); + STATIC_CHECK(std::is_same_v, int const&&>); + + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double&&>); + STATIC_CHECK(std::is_same_v, double const&&>); + + constexpr AdaptedStruct a{42, 3.14}; + + STATIC_CHECK(alloy::get<0>(a) == 42); + STATIC_CHECK(alloy::get<1>(a) == 3.14); + } + + { + STATIC_CHECK(alloy::TupleLike); + + STATIC_CHECK(alloy::tuple_size_v == 2); + + STATIC_CHECK(std::is_same_v, int>); + STATIC_CHECK(std::is_same_v, int>); + STATIC_CHECK(std::is_same_v, std::string const&>); + STATIC_CHECK(std::is_same_v, std::string const&>); + } +} + +TEST_CASE("adapt_std_pair") +{ + { + using Pair = std::pair; + + STATIC_CHECK(alloy::TupleLike); + + STATIC_CHECK(alloy::tuple_size_v == 2); + + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int&&>); + STATIC_CHECK(std::is_same_v, int const&&>); + + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double&&>); + STATIC_CHECK(std::is_same_v, double const&&>); + + constexpr Pair p(42, 3.14); + + STATIC_CHECK(alloy::get<0>(p) == 42); + STATIC_CHECK(alloy::get<1>(p) == 3.14); + } +} + +TEST_CASE("adapt_std_tuple") +{ + { + using Tuple = std::tuple; + + STATIC_CHECK(alloy::TupleLike); + + STATIC_CHECK(alloy::tuple_size_v == 3); + + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int&&>); + STATIC_CHECK(std::is_same_v, int const&&>); + + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double&&>); + STATIC_CHECK(std::is_same_v, double const&&>); + + STATIC_CHECK(std::is_same_v, char&>); + STATIC_CHECK(std::is_same_v, char const&>); + STATIC_CHECK(std::is_same_v, char&&>); + STATIC_CHECK(std::is_same_v, char const&&>); + + constexpr Tuple p(42, 3.14, 'A'); + + STATIC_CHECK(alloy::get<0>(p) == 42); + STATIC_CHECK(alloy::get<1>(p) == 3.14); + STATIC_CHECK(alloy::get<2>(p) == 'A'); + } +} + +TEST_CASE("tuple") +{ + { + STATIC_CHECK(std::is_trivially_default_constructible_v>); + + using Tuple = alloy::tuple; + + STATIC_CHECK(alloy::TupleLike); + + STATIC_CHECK(alloy::tuple_size_v == 3); + + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int&&>); + STATIC_CHECK(std::is_same_v, int const&&>); + + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double&&>); + STATIC_CHECK(std::is_same_v, double const&&>); + + STATIC_CHECK(std::is_same_v, char&>); + STATIC_CHECK(std::is_same_v, char const&>); + STATIC_CHECK(std::is_same_v, char&&>); + STATIC_CHECK(std::is_same_v, char const&&>); + + constexpr Tuple t(42, 3.14, 'A'); + + STATIC_CHECK(alloy::get<0>(t) == 42); + STATIC_CHECK(alloy::get<1>(t) == 3.14); + STATIC_CHECK(alloy::get<2>(t) == 'A'); + } + + { + using Tuple = alloy::tuple; + + STATIC_CHECK(alloy::TupleLike); + STATIC_CHECK(alloy::TupleLikeView); + + STATIC_CHECK(alloy::tuple_size_v == 3); + + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int&>); + STATIC_CHECK(std::is_same_v, int&>); + + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double&>); + STATIC_CHECK(std::is_same_v, double&>); + + STATIC_CHECK(std::is_same_v, char&>); + STATIC_CHECK(std::is_same_v, char&>); + STATIC_CHECK(std::is_same_v, char&>); + STATIC_CHECK(std::is_same_v, char&>); + + int x = 42; + double y = 3.14; + char z = 'A'; + Tuple const t(x, y, z); + + CHECK(alloy::get<0>(t) == 42); + CHECK(alloy::get<1>(t) == 3.14); + CHECK(alloy::get<2>(t) == 'A'); + } + + { + using Tuple = alloy::tuple; + + STATIC_CHECK(alloy::TupleLike); + STATIC_CHECK(alloy::TupleLikeView); + + STATIC_CHECK(alloy::tuple_size_v == 3); + + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int const&>); + STATIC_CHECK(std::is_same_v, int const&>); + + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double const&>); + STATIC_CHECK(std::is_same_v, double const&>); + + STATIC_CHECK(std::is_same_v, char const&>); + STATIC_CHECK(std::is_same_v, char const&>); + STATIC_CHECK(std::is_same_v, char const&>); + STATIC_CHECK(std::is_same_v, char const&>); + + int const x = 42; + double const y = 3.14; + char const z = 'A'; + Tuple const t(x, y, z); + + CHECK(alloy::get<0>(t) == 42); + CHECK(alloy::get<1>(t) == 3.14); + CHECK(alloy::get<2>(t) == 'A'); + } + + { + STATIC_CHECK(std::is_constructible_v, alloy::tuple&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple&&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&&>); + + STATIC_CHECK(std::is_nothrow_constructible_v, alloy::tuple&>); + STATIC_CHECK(std::is_nothrow_constructible_v, alloy::tuple const&>); + STATIC_CHECK(std::is_nothrow_constructible_v, alloy::tuple&&>); + STATIC_CHECK(std::is_nothrow_constructible_v, alloy::tuple const&&>); + + STATIC_CHECK(std::is_convertible_v&, alloy::tuple>); + STATIC_CHECK(std::is_convertible_v const&, alloy::tuple>); + STATIC_CHECK(std::is_convertible_v&&, alloy::tuple>); + STATIC_CHECK(std::is_convertible_v const&&, alloy::tuple>); + + STATIC_CHECK(std::is_nothrow_convertible_v&, alloy::tuple>); + STATIC_CHECK(std::is_nothrow_convertible_v const&, alloy::tuple>); + STATIC_CHECK(std::is_nothrow_convertible_v&&, alloy::tuple>); + STATIC_CHECK(std::is_nothrow_convertible_v const&&, alloy::tuple>); + + struct NeedExplicitConversion + { + explicit NeedExplicitConversion(int) {} + }; + + STATIC_CHECK(std::is_constructible_v, alloy::tuple&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple&&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&&>); + + STATIC_CHECK(!std::is_convertible_v&, alloy::tuple>); + STATIC_CHECK(!std::is_convertible_v const&, alloy::tuple>); + STATIC_CHECK(!std::is_convertible_v&&, alloy::tuple>); + STATIC_CHECK(!std::is_convertible_v const&&, alloy::tuple>); + + struct PotentiallyThrowing + { + PotentiallyThrowing(int) noexcept(false) {} + }; + + STATIC_CHECK(std::is_constructible_v, alloy::tuple&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple&&>); + STATIC_CHECK(std::is_constructible_v, alloy::tuple const&&>); + + STATIC_CHECK(!std::is_nothrow_constructible_v, alloy::tuple&>); + STATIC_CHECK(!std::is_nothrow_constructible_v, alloy::tuple const&>); + STATIC_CHECK(!std::is_nothrow_constructible_v, alloy::tuple&&>); + STATIC_CHECK(!std::is_nothrow_constructible_v, alloy::tuple const&&>); + + alloy::tuple a(42); + alloy::tuple b(a); + CHECK(alloy::get<0>(b) == 42L); + } + + { + STATIC_CHECK(std::is_constructible_v, AdaptedStruct>); + + constexpr AdaptedStruct a{42, 3.14}; + constexpr alloy::tuple t(a); + STATIC_CHECK(alloy::get<0>(t) == 42); + STATIC_CHECK(alloy::get<1>(t) == 3.14); + } + + { + STATIC_CHECK(std::is_nothrow_copy_assignable_v>); + STATIC_CHECK(std::is_nothrow_move_assignable_v>); + + alloy::tuple a(33), b(4); + a = b; + a = std::move(b); + CHECK(alloy::get<0>(a) == 4); + } + + { + STATIC_CHECK(std::is_nothrow_copy_assignable_v>); + STATIC_CHECK(std::is_nothrow_move_assignable_v>); + + int x = 33, y = 4; + alloy::tuple a(x); + alloy::tuple b(y); + a = b; + a = std::move(b); + CHECK(alloy::get<0>(a) == 4); + } + + { + STATIC_CHECK(std::is_assignable_v&, alloy::tuple const&>); + STATIC_CHECK(std::is_assignable_v&, alloy::tuple&&>); + STATIC_CHECK(std::is_nothrow_assignable_v&, alloy::tuple const&>); + STATIC_CHECK(std::is_nothrow_assignable_v&, alloy::tuple&&>); + + alloy::tuple a(33L); + alloy::tuple b(4); + a = b; + a = std::move(b); + CHECK(alloy::get<0>(a) == 4L); + } + + { + STATIC_CHECK(std::is_assignable_v&, AdaptedStruct const&>); + STATIC_CHECK(std::is_assignable_v&, AdaptedStruct&&>); + + alloy::tuple a(33, 3.14); + AdaptedStruct b{4, 2.18}; + a = b; + a = std::move(b); + CHECK(alloy::get<0>(a) == 4); + CHECK(alloy::get<1>(a) == 2.18); + } + + { + alloy::tuple a(33), b(4); + a.swap(b); + swap(a, b); + CHECK(alloy::get<0>(a) == 33); + CHECK(alloy::get<0>(b) == 4); + } + + { + alloy::tuple a(42, 3.14), b = a; + CHECK(a == b); + } + + { + struct Empty + {}; + struct OnlyChar + { + char c; + }; + [[maybe_unused]] constexpr alloy::tuple a = {{}, {'A'}}; + [[maybe_unused]] constexpr alloy::tuple b = {{'A'}, {}}; + STATIC_CHECK(sizeof(a) == sizeof(OnlyChar)); + STATIC_CHECK(sizeof(b) == sizeof(OnlyChar)); + } + + STATIC_CHECK(std::is_same_v, alloy::tuple&>, alloy::tuple>); + STATIC_CHECK(std::is_same_v&>, alloy::tuple>); + +#if __cpp_lib_reference_from_temporary >= 202202L + STATIC_CHECK(!std::is_constructible_v, double>); + STATIC_CHECK(!std::is_constructible_v, double&>); + STATIC_CHECK(!std::is_constructible_v, double&&>); + + STATIC_CHECK(!std::is_constructible_v, alloy::tuple&>); + STATIC_CHECK(!std::is_constructible_v, alloy::tuple&>); + + STATIC_CHECK(!std::is_constructible_v, alloy::tuple const&>); + STATIC_CHECK(!std::is_constructible_v, alloy::tuple const&>); + + STATIC_CHECK(!std::is_constructible_v, alloy::tuple&&>); + STATIC_CHECK(!std::is_constructible_v, alloy::tuple&&>); + + STATIC_CHECK(!std::is_constructible_v, alloy::tuple const&&>); + STATIC_CHECK(!std::is_constructible_v, alloy::tuple const&&>); + + STATIC_CHECK(!std::is_constructible_v, AdaptedStruct>); +#endif +} + +TEST_CASE("utility") +{ + { + constexpr alloy::tuple a(42); + constexpr alloy::tuple b(3.14); + constexpr auto c = alloy::tuple_cat(a, b); + STATIC_CHECK(alloy::get<0>(c) == 42); + STATIC_CHECK(alloy::get<1>(c) == 3.14); + } + + { + constexpr alloy::tuple a(12); + constexpr AdaptedStruct b{34, 3.14}; + constexpr auto c = alloy::tuple_cat(a, b); + STATIC_CHECK(alloy::get<0>(c) == 12); + STATIC_CHECK(alloy::get<1>(c) == 34); + STATIC_CHECK(alloy::get<2>(c) == 3.14); + } + + { + constexpr AdaptedStruct a{12, 3.14}; + constexpr alloy::tuple b(34); + constexpr auto c = alloy::tuple_cat(a, b); + STATIC_CHECK(alloy::get<0>(c) == 12); + STATIC_CHECK(alloy::get<1>(c) == 3.14); + STATIC_CHECK(alloy::get<2>(c) == 34); + } + + { + constexpr AdaptedStruct a{12, 3.14}; + constexpr AdaptedStruct b{34, 2.18}; + constexpr auto c = alloy::tuple_cat(a, b); + STATIC_CHECK(alloy::get<0>(c) == 12); + STATIC_CHECK(alloy::get<1>(c) == 3.14); + STATIC_CHECK(alloy::get<2>(c) == 34); + STATIC_CHECK(alloy::get<3>(c) == 2.18); + } + + { + OldStyle const a{12, "foo"}; + OldStyle const b{34, "bar"}; + auto const c = alloy::tuple_cat(a, b); + CHECK(alloy::get<0>(c) == 12); + CHECK(alloy::get<1>(c) == "foo"); + CHECK(alloy::get<2>(c) == 34); + CHECK(alloy::get<3>(c) == "bar"); + } + + { + constexpr alloy::tuple a(42, 3.14f, 2.18); + constexpr auto b = alloy::tuple_split<1, 2>(a); + STATIC_CHECK(alloy::get<0>(alloy::get<0>(b)) == 42); + STATIC_CHECK(alloy::get<0>(alloy::get<1>(b)) == 3.14f); + STATIC_CHECK(alloy::get<1>(alloy::get<1>(b)) == 2.18); + } + + { + alloy::tuple const from(33, 3.14); + alloy::tuple to(4, 2.18); + alloy::tuple_assign(from, to); + CHECK(alloy::get<0>(to) == 33); + CHECK(alloy::get<1>(to) == 3.14); + } + + { + alloy::tuple from(33, 3.14); + alloy::tuple to(4, 2.18); + alloy::tuple_assign(std::move(from), to); + CHECK(alloy::get<0>(to) == 33); + CHECK(alloy::get<1>(to) == 3.14); + } + + { + alloy::tuple tuple(42, 3.14); + auto view = alloy::tuple_ref(tuple); + CHECK(alloy::get<0>(view) == 42); + CHECK(alloy::get<1>(view) == 3.14); + } + + { + alloy::tuple tuple(42, 3.14); + alloy::for_each(tuple, [](auto& elem) { elem = 33 - 4; }); + CHECK(alloy::get<0>(tuple) == 29); + CHECK(alloy::get<1>(tuple) == 29.); + } +} + +TEST_CASE("io") +{ + { + STATIC_CHECK(iris::req::ADL_ostreamable_v>); + + struct NotStreamable {}; + STATIC_CHECK(!iris::req::ADL_ostreamable_v); + STATIC_CHECK(!iris::req::ADL_ostreamable_v>); + } + { + { + std::stringstream ss; + ss << alloy::tuple<>(); + CHECK(ss.str() == "()"); + } + { + std::stringstream ss; + ss << alloy::tuple(42); + CHECK(ss.str() == "(42)"); + } + { + std::stringstream ss; + ss << alloy::tuple(42, 3.14); + CHECK(ss.str() == "(42, 3.14)"); + } + } +} diff --git a/test/iris_test.hpp b/test/iris_test.hpp index b641494..8b465f5 100644 --- a/test/iris_test.hpp +++ b/test/iris_test.hpp @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MIT -#include +#include // IWYU pragma: keep #include // IWYU pragma: export #include From 9dff87dd80fa6e87c8197143c2540b115e7b4335 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Thu, 20 Aug 2026 23:29:46 +0900 Subject: [PATCH 2/3] Change alloy's license to MIT --- include/iris/alloy/adapt.hpp | 8 +------- include/iris/alloy/adapted/std_pair.hpp | 8 +------- include/iris/alloy/adapted/std_tuple.hpp | 8 +------- include/iris/alloy/detail/deduce.hpp | 8 +------- include/iris/alloy/detail/integer_seq_transform.hpp | 7 +------ .../iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in | 8 +------- include/iris/alloy/detail/tuple_comparison.hpp | 8 +------- include/iris/alloy/detail/tuple_impl.hpp | 8 +------- include/iris/alloy/io.hpp | 8 +------- include/iris/alloy/traits.hpp | 8 +------- include/iris/alloy/tuple.hpp | 8 +------- include/iris/alloy/utility.hpp | 8 +------- scripts/generate_natvis.py | 6 ++---- scripts/generate_tuple_members.bat | 7 ++----- scripts/generate_tuple_members.sh | 7 ++----- test/alloy.cpp | 7 +------ 16 files changed, 19 insertions(+), 103 deletions(-) diff --git a/include/iris/alloy/adapt.hpp b/include/iris/alloy/adapt.hpp index 89399fa..f3ebf23 100644 --- a/include/iris/alloy/adapt.hpp +++ b/include/iris/alloy/adapt.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_ADAPT_HPP #define IRIS_ZZ_ALLOY_ADAPT_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include #include diff --git a/include/iris/alloy/adapted/std_pair.hpp b/include/iris/alloy/adapted/std_pair.hpp index 0f260a8..cc4b9d9 100644 --- a/include/iris/alloy/adapted/std_pair.hpp +++ b/include/iris/alloy/adapted/std_pair.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_ADAPTED_STD_PAIR_HPP #define IRIS_ZZ_ALLOY_ADAPTED_STD_PAIR_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/adapted/std_tuple.hpp b/include/iris/alloy/adapted/std_tuple.hpp index 49a0b1f..1325dc2 100644 --- a/include/iris/alloy/adapted/std_tuple.hpp +++ b/include/iris/alloy/adapted/std_tuple.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_ADAPTED_STD_TUPLE_HPP #define IRIS_ZZ_ALLOY_ADAPTED_STD_TUPLE_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/detail/deduce.hpp b/include/iris/alloy/detail/deduce.hpp index 0f095c5..3e650ff 100644 --- a/include/iris/alloy/detail/deduce.hpp +++ b/include/iris/alloy/detail/deduce.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_DETAIL_DEDUCE_HPP #define IRIS_ZZ_ALLOY_DETAIL_DEDUCE_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/detail/integer_seq_transform.hpp b/include/iris/alloy/detail/integer_seq_transform.hpp index 02ac93e..b7c033c 100644 --- a/include/iris/alloy/detail/integer_seq_transform.hpp +++ b/include/iris/alloy/detail/integer_seq_transform.hpp @@ -1,12 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_DETAIL_INTEGER_SEQ_TRANSFORM_HPP #define IRIS_ZZ_ALLOY_DETAIL_INTEGER_SEQ_TRANSFORM_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in index bea50f6..2c723e5 100644 --- a/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in +++ b/include/iris/alloy/detail/preprocessed/tuple_impl.hpp.pre.in @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_DETAIL_PREPROCESSED_TUPLE_IMPL_HPP #define IRIS_ZZ_ALLOY_DETAIL_PREPROCESSED_TUPLE_IMPL_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/detail/tuple_comparison.hpp b/include/iris/alloy/detail/tuple_comparison.hpp index fcbd69c..33c3375 100644 --- a/include/iris/alloy/detail/tuple_comparison.hpp +++ b/include/iris/alloy/detail/tuple_comparison.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_DETAIL_TUPLE_COMPARISON_HPP #define IRIS_ZZ_ALLOY_DETAIL_TUPLE_COMPARISON_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/detail/tuple_impl.hpp b/include/iris/alloy/detail/tuple_impl.hpp index 547714a..042d15f 100644 --- a/include/iris/alloy/detail/tuple_impl.hpp +++ b/include/iris/alloy/detail/tuple_impl.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_DETAIL_TUPLE_IMPL_HPP #define IRIS_ZZ_ALLOY_DETAIL_TUPLE_IMPL_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #ifndef IRIS_ALLOY_GENERATE_PREPROCESSED diff --git a/include/iris/alloy/io.hpp b/include/iris/alloy/io.hpp index 675515e..f4aa7ab 100644 --- a/include/iris/alloy/io.hpp +++ b/include/iris/alloy/io.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_IO_HPP #define IRIS_ZZ_ALLOY_IO_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/traits.hpp b/include/iris/alloy/traits.hpp index 1f1c2bf..d70909e 100644 --- a/include/iris/alloy/traits.hpp +++ b/include/iris/alloy/traits.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_COMMON_DEF_HPP #define IRIS_ZZ_ALLOY_COMMON_DEF_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include diff --git a/include/iris/alloy/tuple.hpp b/include/iris/alloy/tuple.hpp index 5b21b72..1e6a3c3 100644 --- a/include/iris/alloy/tuple.hpp +++ b/include/iris/alloy/tuple.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_TUPLE_HPP #define IRIS_ZZ_ALLOY_TUPLE_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #ifndef IRIS_USE_PREPROCESSED #define IRIS_USE_PREPROCESSED 1 diff --git a/include/iris/alloy/utility.hpp b/include/iris/alloy/utility.hpp index 0f556a5..9b13cbd 100644 --- a/include/iris/alloy/utility.hpp +++ b/include/iris/alloy/utility.hpp @@ -1,13 +1,7 @@ #ifndef IRIS_ZZ_ALLOY_UTILITY_HPP #define IRIS_ZZ_ALLOY_UTILITY_HPP -/*============================================================================= - Copyright (c) 2025 Yaito Kakeyama - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ +// SPDX-License-Identifier: MIT #include #include diff --git a/scripts/generate_natvis.py b/scripts/generate_natvis.py index 29f4792..b1fc7a4 100644 --- a/scripts/generate_natvis.py +++ b/scripts/generate_natvis.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -# Copyright 2026 The Iris Project Contributors -# -# Distributed under the Boost Software License, Version 1.0. -# https://www.boost.org/LICENSE_1_0.txt + +# SPDX-License-Identifier: MIT N = 32 diff --git a/scripts/generate_tuple_members.bat b/scripts/generate_tuple_members.bat index 2c53063..5ba1997 100644 --- a/scripts/generate_tuple_members.bat +++ b/scripts/generate_tuple_members.bat @@ -1,9 +1,6 @@ -REM Copyright 2026 The Iris Project Contributors -REM -REM Distributed under the Boost Software License, Version 1.0. -REM https://www.boost.org/LICENSE_1_0.txt +REM SPDX-License-Identifier: MIT @echo off -cl /TP /std:c++23preview /Iinclude /Imodules\boost_preprocessor\include /Imodules\iris\include /P /EP /C /DIRIS_ALLOY_GENERATE_PREPROCESSED /Fiinclude\iris\alloy\detail\preprocessed\temp.hpp include\iris\alloy\detail\tuple_impl.hpp +cl /TP /std:c++latest /Iinclude /P /EP /C /DIRIS_ALLOY_GENERATE_PREPROCESSED /Fiinclude\iris\alloy\detail\preprocessed\temp.hpp include\iris\alloy\detail\tuple_impl.hpp pushd include\iris\alloy\detail\preprocessed type tuple_impl.hpp.pre.in temp.hpp tuple_impl.hpp.post.in > temp2.hpp clang-format -i temp2.hpp diff --git a/scripts/generate_tuple_members.sh b/scripts/generate_tuple_members.sh index bba7fe5..4327ca0 100644 --- a/scripts/generate_tuple_members.sh +++ b/scripts/generate_tuple_members.sh @@ -1,9 +1,6 @@ #!/usr/bin/sh -# Copyright 2026 The Iris Project Contributors -# -# Distributed under the Boost Software License, Version 1.0. -# https://www.boost.org/LICENSE_1_0.txt -g++ -Iinclude -Imodules/boost_preprocessor/include -Imodules/iris/include -E -P -DIRIS_ALLOY_GENERATE_PREPROCESSED include/iris/alloy/detail/tuple_impl.hpp > include/iris/alloy/detail/preprocessed/temp.hpp +# SPDX-License-Identifier: MIT +g++ -Iinclude -E -P -DIRIS_ALLOY_GENERATE_PREPROCESSED include/iris/alloy/detail/tuple_impl.hpp > include/iris/alloy/detail/preprocessed/temp.hpp cd include/iris/alloy/detail/preprocessed cat tuple_impl.hpp.pre.in temp.hpp tuple_impl.hpp.post.in > temp2.hpp clang-format -i temp2.hpp diff --git a/test/alloy.cpp b/test/alloy.cpp index 65c4c94..dc366e5 100644 --- a/test/alloy.cpp +++ b/test/alloy.cpp @@ -1,9 +1,4 @@ -/*============================================================================= - Copyright (c) 2026 The Iris Project Contributors - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -=============================================================================*/ +// SPDX-License-Identifier: MIT #include "iris_test.hpp" From dc3f6894dae3bee4c835d5bd205e53dc9c8ba049 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Thu, 20 Aug 2026 23:36:56 +0900 Subject: [PATCH 3/3] Add `chmod +x` to script --- scripts/generate_tuple_members.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/generate_tuple_members.sh diff --git a/scripts/generate_tuple_members.sh b/scripts/generate_tuple_members.sh old mode 100644 new mode 100755