├── .gitignore ├── source ├── bounded │ ├── test │ │ ├── conditional.cpp │ │ ├── assert.cpp │ │ ├── assert-NDEBUG.cpp │ │ ├── to_integer.cpp │ │ ├── check_in_range.cpp │ │ └── stream.cpp │ ├── prevent_comma.cpp │ ├── unchecked.cpp │ ├── function_ptr.cpp │ ├── homogeneous_equals.cpp │ ├── arithmetic │ │ ├── min_max.cpp │ │ ├── test │ │ │ ├── CMakeLists.txt │ │ │ └── pointer.cpp │ │ ├── safe_abs.cpp │ │ ├── extreme_values.cpp │ │ ├── pointer.cpp │ │ ├── round_up_divide.cpp │ │ ├── unary_plus.cpp │ │ ├── bitwise_and.cpp │ │ ├── right_shift.cpp │ │ └── left_shift.cpp │ ├── ordered.cpp │ ├── signed_builtin.cpp │ ├── equality_comparable.cpp │ ├── unsigned_builtin.cpp │ ├── builtin_integer.cpp │ ├── non_const.cpp │ ├── make_index_sequence.cpp │ ├── destroy.cpp │ ├── conditional_function.cpp │ ├── character.cpp │ ├── constexpr_only_if.cpp │ ├── number_of.cpp │ ├── size_of.cpp │ ├── checked_bit_cast.cpp │ ├── type.cpp │ ├── builtin_min_max_value.cpp │ ├── include │ │ └── bounded │ │ │ ├── conditional.hpp │ │ │ ├── arithmetic │ │ │ └── common_arithmetic.hpp │ │ │ └── assert.hpp │ ├── value_fits_in_type.cpp │ ├── declval.cpp │ ├── bounded_integer.cpp │ ├── integral_constant_of_integral.cpp │ ├── copy.cpp │ ├── isomorphic_to_integral.cpp │ ├── integral.cpp │ ├── hash.cpp │ ├── is_bounded_integer.cpp │ ├── value_to_function.cpp │ ├── comparison_builtin.cpp │ ├── scope_fail.cpp │ ├── scope_guard.cpp │ ├── comparison_function_object.cpp │ ├── safe_compare.cpp │ ├── index_sequence_struct.cpp │ ├── safe_equal.cpp │ ├── construct.cpp │ ├── relocate.cpp │ ├── cast.cpp │ ├── stream.cpp │ ├── comparison.cpp │ ├── clamp.cpp │ └── lazy_init.cpp ├── containers │ ├── reserve_space_for.cpp │ ├── has_member_size.cpp │ ├── test │ │ ├── back.cpp │ │ ├── front.cpp │ │ ├── at.cpp │ │ ├── linear_map.cpp │ │ ├── clear.cpp │ │ ├── is_container.cpp │ │ ├── sort │ │ │ ├── fixed_size_merge_sort.cpp │ │ │ ├── to_radix_sort_key.cpp │ │ │ └── test_sort.cpp │ │ ├── push_back.cpp │ │ ├── algorithms │ │ │ ├── count.cpp │ │ │ ├── filter.cpp │ │ │ ├── uninitialized.cpp │ │ │ └── adjacent.cpp │ │ ├── pop_back.cpp │ │ ├── string.cpp │ │ ├── lazy_push_back_into_capacity.cpp │ │ ├── push_front.cpp │ │ ├── lazy_push_back.cpp │ │ ├── lazy_push_front.cpp │ │ ├── push_back_into_capacity.cpp │ │ ├── dynamic_array.cpp │ │ ├── stable_vector.cpp │ │ ├── vector.cpp │ │ └── assign_to_empty.cpp │ ├── subtractable.cpp │ ├── as_mutable_ptr.cpp │ ├── common_functions.cpp │ ├── sentinel_t.cpp │ ├── iterator.cpp │ ├── algorithms │ │ ├── sort │ │ │ ├── relocate_in_order.cpp │ │ │ ├── low_high_ref.cpp │ │ │ ├── rotate_one.cpp │ │ │ ├── cheaply_sortable.cpp │ │ │ ├── sort_exactly_1.cpp │ │ │ ├── sort_exactly_2.cpp │ │ │ ├── dereference_all.cpp │ │ │ └── fixed_size_merge_sort.cpp │ │ ├── destroy_range.cpp │ │ ├── join.cpp │ │ ├── distance.cpp │ │ ├── count.cpp │ │ ├── move_range.cpp │ │ └── keyed_binary_search.cpp │ ├── count_type.cpp │ ├── range_value_t.cpp │ ├── range_reference_t.cpp │ ├── forward_range.cpp │ ├── resizable_container.cpp │ ├── sentinel_for.cpp │ ├── has_member_before_begin.cpp │ ├── random_access_range.cpp │ ├── iterator_t.cpp │ ├── iterator_addable.cpp │ ├── bidirectional_iterator.cpp │ ├── sized_range.cpp │ ├── bidirectional_range.cpp │ ├── member_push_backable.cpp │ ├── random_access_sentinel_for.cpp │ ├── reservable.cpp │ ├── std │ │ └── std_allocator.cpp │ ├── forward_random_access_range.cpp │ ├── member_lazy_push_backable.cpp │ ├── stored_function.cpp │ ├── front.cpp │ ├── splicable.cpp │ ├── size_then_use_range.cpp │ ├── back.cpp │ ├── map_tags.cpp │ ├── forward_random_access_iterator.cpp │ ├── value_wrapper.cpp │ ├── reference_or_value.cpp │ ├── pop_front.cpp │ ├── associative_container.cpp │ ├── offset_type.cpp │ ├── get_source_size.cpp │ ├── extract_key_to_less.cpp │ ├── maximum_array_size.cpp │ ├── reallocation_size.cpp │ ├── random_access_iterator.cpp │ ├── forward_iterator.cpp │ ├── common_iterator_functions.cpp │ ├── index_type.cpp │ ├── linear_size.cpp │ ├── iterator_to_sentinel.cpp │ ├── can_set_size.cpp │ ├── iter_reference_t.cpp │ ├── is_empty.cpp │ ├── iter_value_t.cpp │ ├── emplace_back.cpp │ ├── emplace_front.cpp │ ├── to_string.cpp │ ├── pop_back.cpp │ ├── default_begin_end_size.cpp │ ├── shrink_to_fit.cpp │ ├── dereference.cpp │ ├── initializer_range.cpp │ ├── stable_vector.cpp │ ├── at.cpp │ ├── data.cpp │ ├── key_comparison_function.cpp │ ├── repeat_n.cpp │ ├── iterator_category_base.cpp │ ├── is_container.cpp │ ├── clear.cpp │ ├── range_size_t.cpp │ ├── supports_lazy_insert_after.cpp │ ├── emplace_back_into_capacity.cpp │ ├── member_assign.cpp │ ├── lazy_push_front.cpp │ ├── to_any_string.cpp │ ├── default_adapt_traits.cpp │ ├── iter_difference_t.cpp │ ├── vector.cpp │ ├── push_back.cpp │ ├── erase_concepts.cpp │ ├── c_array.cpp │ ├── lookup.cpp │ └── append_after.cpp ├── tv │ ├── none.cpp │ ├── tv.cpp │ ├── insert.cpp │ ├── single_element_storage.cpp │ ├── indexed_value.cpp │ ├── nth_type.cpp │ ├── is_valid_index.cpp │ ├── tuple_size.cpp │ ├── test │ │ ├── tuple_size.cpp │ │ ├── transform.cpp │ │ ├── is_valid_index.cpp │ │ └── tuple_cat.cpp │ ├── CMakeLists.txt │ └── transform.cpp └── test_assert.hpp ├── .github └── workflows │ └── build-and-test.yml ├── .gitmodules ├── containers-readme.md ├── LICENSE_1_0.txt ├── readme.md └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | .vscode/ 3 | -------------------------------------------------------------------------------- /source/bounded/test/conditional.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.conditional; -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | 3 | on: 4 | schedule: 5 | - cron: '27 5 * * *' 6 | push: 7 | branches: [ "main" ] 8 | pull_request: 9 | branches: [ "main" ] 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: davidstone/cmake_strict_defaults@main 17 | -------------------------------------------------------------------------------- /source/bounded/prevent_comma.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.prevent_comma; 7 | 8 | namespace bounded::detail { 9 | 10 | export auto prevent_comma(auto &&) -> void; 11 | 12 | } // namespace bounded::detail -------------------------------------------------------------------------------- /source/bounded/unchecked.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.unchecked; 7 | 8 | namespace bounded { 9 | 10 | export struct unchecked_t { 11 | }; 12 | export constexpr auto unchecked = unchecked_t(); 13 | 14 | } // namespace bounded 15 | -------------------------------------------------------------------------------- /source/bounded/function_ptr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.function_ptr; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | using function_ptr = Result(*)(Args...); 12 | 13 | } // namespace bounded 14 | -------------------------------------------------------------------------------- /source/bounded/homogeneous_equals.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.homogeneous_equals; 7 | 8 | export template 9 | constexpr auto homogeneous_equals(T const & result, T const & expected) -> bool { 10 | return result == expected; 11 | } 12 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/min_max.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.min_max; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | struct min_max { 12 | Min min; 13 | Max max; 14 | }; 15 | 16 | } // namespace bounded 17 | -------------------------------------------------------------------------------- /source/containers/reserve_space_for.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.reserve_space_for; 7 | 8 | namespace containers { 9 | 10 | export template 11 | struct reserve_space_for { 12 | Capacity value; 13 | }; 14 | 15 | } // namespace containers 16 | -------------------------------------------------------------------------------- /source/bounded/ordered.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.ordered; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | concept ordered = requires(LHS const & lhs, RHS const & rhs) { lhs <=> rhs; }; 12 | 13 | } // namespace bounded 14 | -------------------------------------------------------------------------------- /source/containers/has_member_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.has_member_size; 7 | 8 | namespace containers { 9 | 10 | export template 11 | concept has_member_size = requires(Range const & range) { range.size(); }; 12 | 13 | } // namespace containers -------------------------------------------------------------------------------- /source/bounded/signed_builtin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.signed_builtin; 7 | 8 | import numeric_traits; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | concept signed_builtin = numeric_traits::signed_builtin; 14 | 15 | } // namespace bounded 16 | -------------------------------------------------------------------------------- /source/containers/test/back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.back; 7 | 8 | import containers.array; 9 | import containers.back; 10 | 11 | static_assert(containers::back(containers::array({5})) == 5); 12 | static_assert(containers::back(containers::array({2, 3, 4})) == 4); -------------------------------------------------------------------------------- /source/containers/test/front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.front; 7 | 8 | import containers.array; 9 | import containers.front; 10 | 11 | static_assert(containers::front(containers::array({5})) == 5); 12 | static_assert(containers::front(containers::array({2, 3, 4})) == 2); -------------------------------------------------------------------------------- /source/containers/subtractable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.subtractable; 7 | 8 | namespace containers { 9 | 10 | export template 11 | concept subtractable = requires(LHS const lhs, RHS const rhs) { lhs - rhs; }; 12 | 13 | } // namespace containers 14 | -------------------------------------------------------------------------------- /source/containers/as_mutable_ptr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.as_mutable_ptr; 7 | 8 | namespace containers { 9 | 10 | export template 11 | constexpr auto as_mutable_ptr(T const * value) -> T * { 12 | return const_cast(value); 13 | } 14 | 15 | } // namespace containers 16 | -------------------------------------------------------------------------------- /source/bounded/equality_comparable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.equality_comparable; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | concept equality_comparable = requires(LHS const & lhs, RHS const & rhs) { lhs == rhs; }; 12 | 13 | } // namespace bounded 14 | -------------------------------------------------------------------------------- /source/containers/common_functions.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.common_functions; 11 | 12 | import bounded; 13 | 14 | namespace containers { 15 | 16 | BOUNDED_COMMON_ARITHMETIC(export) 17 | 18 | } // namespace containers 19 | -------------------------------------------------------------------------------- /source/containers/test/at.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | 8 | import containers.array; 9 | import containers.at; 10 | 11 | namespace { 12 | 13 | TEST_CASE("at throws for out-of-bounds", "[at]") { 14 | CHECK_THROWS(containers::at(containers::array({1}), 1U)); 15 | } 16 | 17 | } // namespace -------------------------------------------------------------------------------- /source/tv/none.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.none; 7 | 8 | namespace tv { 9 | 10 | // none_t cannot be default constructible or we get an ambiguity in op = {}; 11 | export struct none_t { 12 | constexpr explicit none_t(int) {} 13 | }; 14 | export constexpr auto none = none_t(0); 15 | 16 | } // namespace tv 17 | -------------------------------------------------------------------------------- /source/containers/sentinel_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.sentinel_t; 7 | 8 | import containers.begin_end; 9 | 10 | import bounded; 11 | 12 | namespace containers { 13 | 14 | export template 15 | using sentinel_t = decltype(containers::end(bounded::declval())); 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/bounded/unsigned_builtin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.unsigned_builtin; 7 | 8 | import numeric_traits; 9 | import std_module; 10 | 11 | namespace bounded { 12 | 13 | export template 14 | concept unsigned_builtin = numeric_traits::unsigned_builtin and !std::same_as; 15 | 16 | } // namespace bounded 17 | -------------------------------------------------------------------------------- /source/containers/iterator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.iterator; 7 | 8 | import bounded; 9 | import std_module; 10 | 11 | namespace containers { 12 | 13 | export template 14 | concept iterator = requires(std::remove_cvref_t it) { 15 | *it; 16 | ++it; 17 | }; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/bounded/builtin_integer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.builtin_integer; 7 | 8 | import bounded.signed_builtin; 9 | import bounded.unsigned_builtin; 10 | 11 | namespace bounded { 12 | 13 | export template 14 | concept builtin_integer = 15 | signed_builtin or 16 | unsigned_builtin; 17 | 18 | } // namespace bounded -------------------------------------------------------------------------------- /source/bounded/non_const.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.non_const; 7 | 8 | import std_module; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | concept non_const = !std::is_const_v; 14 | 15 | } // namespace bounded 16 | 17 | static_assert(bounded::non_const); 18 | static_assert(!bounded::non_const); -------------------------------------------------------------------------------- /source/containers/algorithms/sort/relocate_in_order.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.relocate_in_order; 7 | 8 | import bounded; 9 | 10 | namespace containers { 11 | 12 | export constexpr auto relocate_in_order(auto it, auto & ... xs) { 13 | (..., bounded::relocate_at(*it++, xs)); 14 | } 15 | 16 | } // namespace containers 17 | -------------------------------------------------------------------------------- /source/bounded/make_index_sequence.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.make_index_sequence; 7 | 8 | import bounded.integer; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | export template 15 | constexpr auto make_index_sequence(constant_t) { 16 | return std::make_index_sequence{}; 17 | } 18 | 19 | } // namespace bounded -------------------------------------------------------------------------------- /source/containers/count_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.count_type; 7 | 8 | import containers.iterator_t; 9 | import containers.offset_type; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | using count_type = offset_type>; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright David Stone 2024. 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | add_library(bounded_arithmetic_test) 7 | 8 | target_sources(bounded_arithmetic_test PRIVATE 9 | FILE_SET CXX_MODULES 10 | BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" 11 | FILES 12 | pointer.cpp 13 | ) 14 | 15 | target_link_libraries(bounded_arithmetic_test PUBLIC 16 | bounded 17 | strict_defaults 18 | ) 19 | -------------------------------------------------------------------------------- /source/containers/range_value_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.range_value_t; 7 | 8 | import containers.iter_value_t; 9 | import containers.iterator_t; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | using range_value_t = iter_value_t>; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/bounded/destroy.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.destroy; 7 | 8 | import bounded.non_const; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | export constexpr auto destroy = [](T & ref) noexcept(std::is_nothrow_destructible_v) -> void { 15 | std::destroy_at(std::addressof(ref)); 16 | }; 17 | 18 | } // namespace bounded 19 | -------------------------------------------------------------------------------- /source/bounded/conditional_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.conditional_function; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | constexpr auto conditional_function(auto if_true, auto if_false) { 12 | if constexpr (condition) { 13 | return if_true; 14 | } else { 15 | return if_false; 16 | } 17 | }; 18 | 19 | } // namespace bounded 20 | -------------------------------------------------------------------------------- /source/containers/range_reference_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.range_reference_t; 7 | 8 | import containers.iter_reference_t; 9 | import containers.iterator_t; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | using range_reference_t = iter_reference_t>; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/containers/forward_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.forward_range; 7 | 8 | import containers.forward_iterator; 9 | import containers.iterator_t; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept forward_range = 16 | range and 17 | forward_iterator>; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/safe_abs.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.safe_abs; 7 | 8 | import numeric_traits; 9 | 10 | namespace bounded { 11 | 12 | export constexpr auto safe_abs = [](auto const value) { 13 | return (value < 0) ? -static_cast(value) : static_cast(value); 14 | }; 15 | 16 | } // namespace bounded 17 | -------------------------------------------------------------------------------- /source/bounded/character.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.character; 7 | 8 | import std_module; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | concept character = 14 | std::same_as or 15 | std::same_as or 16 | std::same_as or 17 | std::same_as or 18 | std::same_as; 19 | 20 | } // namespace bounded 21 | -------------------------------------------------------------------------------- /source/containers/resizable_container.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.resizable_container; 7 | 8 | import containers.pop_back; 9 | import containers.push_back; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept resizable_container = push_backable and pop_backable and range; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/containers/sentinel_for.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.sentinel_for; 7 | 8 | import containers.iterator; 9 | 10 | import bounded; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept sentinel_for = 16 | iterator and 17 | bounded::equality_comparable; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/algorithms/sort/low_high_ref.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.low_high_ref; 7 | 8 | namespace containers { 9 | 10 | export template 11 | struct low_high_ref { 12 | constexpr low_high_ref(T & low_, T & high_): 13 | low(low_), 14 | high(high_) 15 | { 16 | } 17 | 18 | T & low; 19 | T & high; 20 | }; 21 | 22 | } // namespace containers 23 | -------------------------------------------------------------------------------- /source/containers/has_member_before_begin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.has_member_before_begin; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept has_member_before_begin = requires(Range range) { 16 | OPERATORS_FORWARD(range).before_begin(); 17 | }; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/random_access_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.random_access_range; 7 | 8 | import containers.bidirectional_range; 9 | import containers.forward_random_access_range; 10 | 11 | namespace containers { 12 | 13 | export template 14 | concept random_access_range = bidirectional_range and forward_random_access_range; 15 | 16 | } // namespace containers 17 | -------------------------------------------------------------------------------- /source/containers/iterator_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.iterator_t; 7 | 8 | import containers.begin_end; 9 | import containers.range; 10 | 11 | import bounded; 12 | import std_module; 13 | 14 | namespace containers { 15 | 16 | export template 17 | using iterator_t = std::remove_cvref_t()))>; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/iterator_addable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.iterator_addable; 7 | 8 | import std_module; 9 | 10 | namespace containers { 11 | 12 | export template 13 | concept iterator_addable = requires(Iterator it, Offset const offset) { 14 | { std::move(it) + offset } -> std::same_as>; 15 | }; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/bounded/constexpr_only_if.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.constexpr_only_if; 7 | 8 | import bounded.concepts; 9 | 10 | namespace bounded::detail { 11 | 12 | auto non_constexpr() -> void { 13 | } 14 | 15 | export constexpr auto constexpr_only_if(explicitly_convertible_to auto const & condition) -> void { 16 | if (!condition) { 17 | non_constexpr(); 18 | } 19 | } 20 | 21 | } // namespace bounded::detail -------------------------------------------------------------------------------- /source/bounded/number_of.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.number_of; 7 | 8 | import bounded.integer; 9 | import bounded.isomorphic_to_integral; 10 | 11 | import numeric_traits; 12 | 13 | namespace bounded { 14 | 15 | export template 16 | constexpr auto number_of = constant> - constant> + constant<1>; 17 | 18 | } // namespace bounded 19 | -------------------------------------------------------------------------------- /source/containers/bidirectional_iterator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.bidirectional_iterator; 7 | 8 | import containers.forward_iterator; 9 | 10 | import std_module; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept bidirectional_iterator = 16 | forward_iterator and 17 | requires(std::remove_cvref_t it) { --it; }; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/sized_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.sized_range; 7 | 8 | import containers.forward_random_access_range; 9 | import containers.has_member_size; 10 | import containers.range; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept sized_range = (range and has_member_size) or forward_random_access_range; 16 | 17 | } // namespace containers 18 | -------------------------------------------------------------------------------- /source/containers/bidirectional_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.bidirectional_range; 7 | 8 | import containers.bidirectional_iterator; 9 | import containers.forward_range; 10 | import containers.iterator_t; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept bidirectional_range = 16 | forward_range and 17 | bidirectional_iterator>; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/member_push_backable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.member_push_backable; 7 | 8 | import containers.range_value_t; 9 | 10 | import std_module; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept member_push_backable = requires(Container & container, range_value_t value) { 16 | container.push_back(std::move(value)); 17 | }; 18 | 19 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/random_access_sentinel_for.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.random_access_sentinel_for; 7 | 8 | import containers.sentinel_for; 9 | import containers.subtractable; 10 | 11 | namespace containers { 12 | 13 | export template 14 | concept random_access_sentinel_for = 15 | sentinel_for and 16 | subtractable; 17 | 18 | } // namespace containers 19 | -------------------------------------------------------------------------------- /source/containers/reservable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.reservable; 7 | 8 | import containers.range_size_t; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | using namespace bounded::literal; 14 | 15 | namespace containers { 16 | 17 | export template 18 | concept reservable = requires(Container & container, range_size_t size) { container.reserve(size); }; 19 | 20 | } // namespace containers 21 | -------------------------------------------------------------------------------- /source/bounded/size_of.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.size_of; 11 | 12 | import bounded.integer; 13 | 14 | namespace bounded { 15 | 16 | export template 17 | constexpr auto size_of = constant; 18 | 19 | export constexpr auto char_bit = constant; 20 | 21 | export template 22 | constexpr auto size_of_bits = size_of * char_bit; 23 | 24 | } // namespace bounded 25 | -------------------------------------------------------------------------------- /source/containers/std/std_allocator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.std.std_allocator; 7 | 8 | import std_module; 9 | 10 | namespace std_containers { 11 | 12 | template 13 | constexpr auto is_std_allocator = false; 14 | 15 | template 16 | constexpr auto is_std_allocator> = true; 17 | 18 | export template 19 | concept std_allocator = is_std_allocator; 20 | 21 | } // namespace std_containers 22 | -------------------------------------------------------------------------------- /source/bounded/test/assert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #undef NDEBUG 9 | #undef BOUNDED_NDEBUG 10 | 11 | #include 12 | 13 | export module bounded.assert; 14 | 15 | static_assert([]{ BOUNDED_ASSERT(true); return true; }()); 16 | // static_assert([]{ BOUNDED_ASSERT(false); return true; }()); 17 | static_assert([]{ BOUNDED_ASSERT_OR_ASSUME(true); return true; }()); 18 | // static_assert([]{ BOUNDED_ASSERT_OR_ASSUME(false); return true; }()); 19 | 20 | -------------------------------------------------------------------------------- /source/tv/tv.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv; 7 | 8 | export import tv.indexed_value; 9 | export import tv.insert; 10 | export import tv.none; 11 | export import tv.optional; 12 | export import tv.overload; 13 | export import tv.single_element_storage; 14 | export import tv.transform; 15 | export import tv.tuple; 16 | export import tv.tuple_cat; 17 | export import tv.tuple_size; 18 | export import tv.variant; 19 | export import tv.variant_index; 20 | export import tv.visit; -------------------------------------------------------------------------------- /source/containers/forward_random_access_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.forward_random_access_range; 7 | 8 | import containers.forward_random_access_iterator; 9 | import containers.forward_range; 10 | import containers.iterator_t; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept forward_random_access_range = 16 | forward_range and 17 | forward_random_access_iterator>; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/bounded/checked_bit_cast.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.checked_bit_cast; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.check_in_range; 10 | 11 | import std_module; 12 | 13 | namespace bounded { 14 | 15 | export template 16 | constexpr auto checked_bit_cast(Source const source) -> T { 17 | return bounded::check_in_range(std::bit_cast(source)); 18 | } 19 | 20 | } // namespace bounded 21 | -------------------------------------------------------------------------------- /source/bounded/test/assert-NDEBUG.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #undef NDEBUG 9 | #define NDEBUG 10 | 11 | #include 12 | 13 | export module bounded.assert_NDEBUG; 14 | 15 | static_assert([]{ BOUNDED_ASSERT(true); return true; }()); 16 | // static_assert([]{ BOUNDED_ASSERT(false); return true; }()); 17 | static_assert([]{ BOUNDED_ASSERT_OR_ASSUME(true); return true; }()); 18 | // static_assert([]{ BOUNDED_ASSERT_OR_ASSUME(false); return true; }()); 19 | 20 | -------------------------------------------------------------------------------- /source/containers/member_lazy_push_backable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.member_lazy_push_backable; 7 | 8 | import containers.range_value_t; 9 | 10 | import bounded; 11 | 12 | namespace containers { 13 | 14 | export template 15 | concept member_lazy_push_backable = 16 | requires(Container container, bounded::function_ptr> constructor) { 17 | container.lazy_push_back(constructor); 18 | }; 19 | 20 | } // namespace containers 21 | -------------------------------------------------------------------------------- /source/bounded/type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.type; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | struct type_t { 12 | using type = T; 13 | 14 | friend constexpr auto operator==(type_t, type_t) -> bool = default; 15 | template 16 | friend constexpr auto operator==(type_t, type_t) -> bool { 17 | return false; 18 | } 19 | }; 20 | 21 | export template 22 | constexpr auto type = type_t(); 23 | 24 | } // namespace bounded 25 | -------------------------------------------------------------------------------- /source/bounded/builtin_min_max_value.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.builtin_min_max_value; 7 | 8 | import bounded.normalize; 9 | import numeric_traits; 10 | 11 | namespace bounded { 12 | 13 | export template 14 | constexpr auto builtin_max_value = normalize>; 15 | 16 | export template 17 | constexpr auto builtin_min_value = normalize>; 18 | 19 | } // namespace bounded -------------------------------------------------------------------------------- /source/bounded/include/bounded/conditional.hpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef BOUNDED_CONDITIONAL_HPP 7 | #define BOUNDED_CONDITIONAL_HPP 8 | 9 | import bounded.common_type_and_value_category; 10 | 11 | #define BOUNDED_CONDITIONAL(condition, lhs, rhs) \ 12 | ((condition) ? \ 13 | static_cast>(lhs) : \ 14 | static_cast>(rhs)) 15 | 16 | #endif // BOUNDED_CONDITIONAL_HPP -------------------------------------------------------------------------------- /source/bounded/value_fits_in_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.value_fits_in_type; 7 | 8 | import bounded.builtin_min_max_value; 9 | import bounded.comparison; 10 | import bounded.safe_compare; 11 | 12 | namespace bounded { 13 | 14 | export template 15 | constexpr auto value_fits_in_type(auto const value) { 16 | return 17 | safe_compare(builtin_min_value, value) <= 0 and 18 | safe_compare(value, builtin_max_value) <= 0; 19 | } 20 | 21 | } // namespace bounded 22 | -------------------------------------------------------------------------------- /source/containers/algorithms/destroy_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.algorithms.destroy_range; 11 | 12 | import containers.begin_end; 13 | import containers.range; 14 | 15 | import bounded; 16 | 17 | namespace containers { 18 | 19 | export constexpr void destroy_range(range auto && r) { 20 | for (auto & value : OPERATORS_FORWARD(r)) { 21 | bounded::destroy(value); 22 | } 23 | } 24 | 25 | } // namespace containers 26 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/test/pointer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.test.pointer; 7 | 8 | import bounded.arithmetic.pointer; 9 | 10 | import bounded.bounded_integer; 11 | import bounded.literal; 12 | 13 | import std_module; 14 | 15 | namespace { 16 | using namespace bounded::literal; 17 | 18 | constexpr int array[5] = {}; 19 | 20 | static_assert(std::begin(array) + 0_bi == std::begin(array)); 21 | static_assert(std::begin(array) + 5_bi == std::end(array)); 22 | 23 | } // namespace -------------------------------------------------------------------------------- /source/containers/stored_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.stored_function; 7 | 8 | import containers.reference_or_value; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | export template 16 | using stored_function = std::conditional_t< 17 | std::invocable, 18 | reference_or_value, 19 | std::reference_wrapper 20 | >; 21 | 22 | } // namespace containers 23 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/extreme_values.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.extreme_values; 7 | 8 | import bounded.integer; 9 | import numeric_traits; 10 | 11 | export constexpr auto signed_max = bounded::constant>; 12 | export constexpr auto signed_min = bounded::constant>; 13 | export constexpr auto unsigned_max = bounded::constant>; 14 | -------------------------------------------------------------------------------- /source/containers/front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | #include 10 | 11 | export module containers.front; 12 | 13 | import containers.begin_end; 14 | import containers.is_empty; 15 | import containers.range; 16 | 17 | namespace containers { 18 | 19 | export constexpr auto front(range auto && r) -> decltype(auto) { 20 | BOUNDED_ASSERT(!containers::is_empty(r)); 21 | return *containers::begin(OPERATORS_FORWARD(r)); 22 | } 23 | 24 | } // namespace containers -------------------------------------------------------------------------------- /source/test_assert.hpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef BOUNDED_TEST_ASSERT_HPP 7 | #define BOUNDED_TEST_ASSERT_HPP 8 | 9 | #if defined NDEBUG 10 | #define BOUNDED_NDEBUG_WAS_DEFINED NDEBUG 11 | #undef NDEBUG 12 | #endif 13 | 14 | #include 15 | 16 | // Like assert, but always evaluated 17 | #define BOUNDED_TEST(...) assert((__VA_ARGS__)) 18 | 19 | #if defined BOUNDED_NDEBUG_WAS_DEFINED 20 | #define NDEBUG BOUNDED_NDEBUG_WAS_DEFINED 21 | #undef BOUNDED_NDEBUG_WAS_DEFINED 22 | #endif 23 | 24 | #endif // BOUNDED_TEST_ASSERT_HPP -------------------------------------------------------------------------------- /source/bounded/arithmetic/pointer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.pointer; 7 | 8 | import bounded.bounded_integer; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | constexpr auto operator+(T * const & ptr, bounded_integer auto const number) -> T * { 14 | return ptr + number.value(); 15 | } 16 | 17 | 18 | export template 19 | constexpr auto operator+(bounded_integer auto const number, T * const & ptr) -> T * { 20 | return number.value() + ptr; 21 | } 22 | 23 | } // namespace bounded -------------------------------------------------------------------------------- /source/bounded/declval.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.declval; 7 | 8 | import std_module; 9 | 10 | namespace bounded { 11 | 12 | // TODO: File a bug against the standard? The standard version always returns a 13 | // reference, which means it does not work with guaranteed copy elision. 14 | export template 15 | auto declval() noexcept -> T; 16 | 17 | export template requires (std::is_function_v> or std::is_array_v>) 18 | auto declval() noexcept -> T &&; 19 | 20 | } // namespace bounded 21 | -------------------------------------------------------------------------------- /source/containers/splicable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.splicable; 7 | 8 | import containers.iterator_t; 9 | 10 | namespace containers { 11 | 12 | // splice is required to be constant time 13 | export template 14 | concept splicable = requires( 15 | Container target, 16 | iterator_t position, 17 | Container source, 18 | iterator_t first, 19 | iterator_t last 20 | ) { 21 | target.splice(position, source, first, last); 22 | }; 23 | 24 | } // namespace containers 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "benchmark"] 2 | path = dependencies/benchmark 3 | url = https://github.com/google/benchmark.git 4 | [submodule "Catch2"] 5 | path = dependencies/Catch2 6 | url = https://github.com/catchorg/Catch2.git 7 | [submodule "cmake_strict_defaults"] 8 | path = dependencies/cmake_strict_defaults 9 | url = https://github.com/davidstone/cmake_strict_defaults 10 | [submodule "numeric-traits"] 11 | path = dependencies/numeric-traits 12 | url = https://github.com/davidstone/numeric-traits 13 | [submodule "operators"] 14 | path = dependencies/operators 15 | url = https://github.com/davidstone/operators.git 16 | [submodule "dependencies/std_module"] 17 | path = dependencies/std_module 18 | url = https://github.com/davidstone/std_module.git 19 | -------------------------------------------------------------------------------- /source/containers/size_then_use_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.size_then_use_range; 7 | 8 | import containers.forward_range; 9 | import containers.sized_range; 10 | 11 | namespace containers { 12 | 13 | // A range that you can get the size from and still access elements in the 14 | // range. An unsized input range is an example of a range that does not model 15 | // this concept. 16 | export template 17 | concept size_then_use_range = forward_range or sized_range; 18 | 19 | } // namespace containers 20 | -------------------------------------------------------------------------------- /source/containers/back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | #include 10 | 11 | export module containers.back; 12 | 13 | import containers.algorithms.advance; 14 | import containers.begin_end; 15 | import containers.is_empty; 16 | import containers.range; 17 | 18 | namespace containers { 19 | 20 | export constexpr auto back(range auto && r) -> decltype(auto) { 21 | BOUNDED_ASSERT(!containers::is_empty(r)); 22 | return *containers::prev(containers::end(OPERATORS_FORWARD(r))); 23 | } 24 | 25 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/test/linear_map.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.linear_map; 7 | 8 | import containers.test.test_associative_container; 9 | import containers.test.test_reserve_and_capacity; 10 | 11 | import containers.linear_map; 12 | 13 | import bounded.test_int; 14 | 15 | using non_copyable_map = containers::linear_map; 16 | 17 | static_assert(containers_test::test_reserve_and_capacity()); 18 | static_assert(containers_test::test_associative_container()); 19 | -------------------------------------------------------------------------------- /source/bounded/bounded_integer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.bounded_integer; 7 | 8 | import bounded.is_bounded_integer; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | concept bounded_integer = is_bounded_integer; 14 | 15 | } // namespace bounded 16 | 17 | namespace { 18 | 19 | enum e { 20 | }; 21 | 22 | struct s { 23 | }; 24 | 25 | static_assert(!bounded::bounded_integer); 26 | static_assert(!bounded::bounded_integer); 27 | static_assert(!bounded::bounded_integer); 28 | static_assert(!bounded::bounded_integer); 29 | 30 | } // namespace -------------------------------------------------------------------------------- /source/containers/map_tags.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.map_tags; 7 | 8 | namespace containers { 9 | 10 | export struct assume_sorted_unique_t {}; 11 | export constexpr auto assume_sorted_unique = assume_sorted_unique_t(); 12 | 13 | export struct assume_unique_t {}; 14 | export constexpr auto assume_unique = assume_unique_t(); 15 | 16 | export template 17 | struct inserted_t { 18 | Iterator iterator; 19 | bool inserted; 20 | }; 21 | 22 | template 23 | inserted_t(Iterator, bool) -> inserted_t; 24 | 25 | } // namespace containers -------------------------------------------------------------------------------- /source/bounded/integral_constant_of_integral.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.integral_constant_of_integral; 7 | 8 | import bounded.builtin_integer; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | template 15 | constexpr auto is_integral_constant_of_integral = false; 16 | 17 | template 18 | constexpr auto is_integral_constant_of_integral> = builtin_integer; 19 | 20 | export template 21 | concept integral_constant_of_integral = is_integral_constant_of_integral; 22 | 23 | } // namespace bounded -------------------------------------------------------------------------------- /source/containers/forward_random_access_iterator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.forward_random_access_iterator; 7 | 8 | import containers.forward_iterator; 9 | import containers.iterator_addable; 10 | import containers.offset_type; 11 | import containers.subtractable; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | export template 19 | concept forward_random_access_iterator = 20 | forward_iterator and 21 | subtractable and 22 | iterator_addable>; 23 | 24 | } // namespace containers 25 | -------------------------------------------------------------------------------- /source/containers/value_wrapper.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.value_wrapper; 7 | 8 | import std_module; 9 | 10 | namespace containers { 11 | 12 | export template 13 | struct value_wrapper { 14 | using type = T; 15 | value_wrapper() = default; 16 | constexpr value_wrapper(T value): 17 | m_value(std::move(value)) 18 | { 19 | } 20 | constexpr auto get() const & -> T const & { 21 | return m_value; 22 | } 23 | constexpr auto get() && -> T && { 24 | return std::move(m_value); 25 | } 26 | private: 27 | [[no_unique_address]] T m_value; 28 | }; 29 | 30 | } // namespace containers 31 | -------------------------------------------------------------------------------- /source/containers/reference_or_value.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.reference_or_value; 7 | 8 | import containers.value_wrapper; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | template 16 | constexpr auto can_store_copy = 17 | bounded::mostly_trivial and 18 | sizeof(T) <= sizeof(std::reference_wrapper); 19 | 20 | export template 21 | using reference_or_value = std::conditional_t< 22 | can_store_copy, 23 | value_wrapper>, 24 | std::reference_wrapper 25 | >; 26 | 27 | } // namespace containers 28 | -------------------------------------------------------------------------------- /source/containers/pop_front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.pop_front; 7 | 8 | import containers.algorithms.erase; 9 | import containers.begin_end; 10 | import containers.erase_concepts; 11 | 12 | namespace containers { 13 | 14 | export template 15 | constexpr auto pop_front(Container & c) -> void { 16 | if constexpr (member_pop_frontable) { 17 | c.pop_front(); 18 | } else if constexpr (constant_time_erasable) { 19 | containers::erase(c, containers::begin(c)); 20 | } else { 21 | c.erase_after(c.before_begin()); 22 | } 23 | } 24 | 25 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/associative_container.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.associative_container; 7 | 8 | import containers.forward_range; 9 | import containers.is_container; 10 | 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | export template 16 | concept associative_range = 17 | forward_range and 18 | requires { 19 | typename std::remove_reference_t::key_type; 20 | typename std::remove_reference_t::mapped_type; 21 | }; 22 | 23 | export template 24 | concept associative_container = associative_range and is_container; 25 | 26 | } // namespace containers 27 | -------------------------------------------------------------------------------- /source/containers/offset_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.offset_type; 7 | 8 | import containers.iter_difference_t; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | export template 16 | using to_offset_type = std::conditional_t< 17 | bounded::bounded_integer, 18 | bounded::integer<0, bounded::builtin_max_value>, 19 | T 20 | >; 21 | 22 | export template 23 | using offset_type = to_offset_type>; 24 | 25 | } // namespace containers 26 | 27 | static_assert(std::same_as, std::ptrdiff_t>); 28 | -------------------------------------------------------------------------------- /source/tv/insert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | #include 10 | 11 | export module tv.insert; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace tv { 17 | 18 | export constexpr auto insert(auto & destination, auto position, auto && value) OPERATORS_RETURNS( 19 | destination.emplace(std::move(position), bounded::value_to_function(OPERATORS_FORWARD(value))) 20 | ) 21 | 22 | export constexpr auto insert(auto & destination, auto && value) OPERATORS_RETURNS( 23 | destination.emplace(bounded::value_to_function(OPERATORS_FORWARD(value))) 24 | ) 25 | 26 | } // namespace tv -------------------------------------------------------------------------------- /source/containers/get_source_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.get_source_size; 7 | 8 | import containers.linear_size; 9 | import containers.range_size_t; 10 | import containers.size_then_use_range; 11 | 12 | import bounded; 13 | 14 | namespace containers { 15 | 16 | export template 17 | constexpr auto get_source_size(size_then_use_range auto && source) { 18 | auto const value = containers::linear_size(source); 19 | if constexpr (bounded::bounded_integer) { 20 | return value; 21 | } else { 22 | return ::bounded::assume_in_range>(value); 23 | } 24 | }; 25 | 26 | } // namespace containers 27 | -------------------------------------------------------------------------------- /source/containers/extract_key_to_less.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.extract_key_to_less; 7 | 8 | import std_module; 9 | 10 | namespace containers { 11 | 12 | export template 13 | struct extract_key_to_less { 14 | extract_key_to_less() = default; 15 | explicit constexpr extract_key_to_less(ExtractKey extract_key): 16 | m_extract_key(std::move(extract_key)) 17 | { 18 | } 19 | 20 | constexpr auto operator()(auto const & lhs, auto const & rhs) const { 21 | return m_extract_key(lhs) < m_extract_key(rhs); 22 | } 23 | 24 | private: 25 | [[no_unique_address]] ExtractKey m_extract_key; 26 | }; 27 | 28 | } // namespace containers 29 | -------------------------------------------------------------------------------- /source/bounded/copy.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.copy; 11 | 12 | import bounded.concepts; 13 | 14 | import std_module; 15 | 16 | namespace bounded { 17 | 18 | // Works with explicit copy constructors 19 | // TODO: make this a lambda after resolution of 20 | // https://github.com/llvm/llvm-project/issues/59513 21 | struct copy_t { 22 | template 23 | static constexpr auto operator()(T && value) requires constructible_from, T &&> { 24 | return std::decay_t(OPERATORS_FORWARD(value)); 25 | } 26 | }; 27 | export constexpr auto copy = copy_t(); 28 | 29 | } // namespace bounded 30 | -------------------------------------------------------------------------------- /source/bounded/test/to_integer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.to_integer_test; 11 | 12 | import bounded.to_integer; 13 | 14 | import std_module; 15 | 16 | TEST_CASE("to_integer", "[to_integer]") { 17 | CHECK_THROWS_AS((bounded::to_integer<0, 0>("")), std::invalid_argument); 18 | CHECK_THROWS_AS((bounded::to_integer<-1, 1>("-")), std::invalid_argument); 19 | CHECK_THROWS_AS((bounded::to_integer<0, 0>("1")), std::invalid_argument); 20 | CHECK_THROWS_AS((bounded::to_integer<0, 100>("101")), std::invalid_argument); 21 | CHECK_THROWS_AS((bounded::to_integer<0, 100>("-90")), std::invalid_argument); 22 | } 23 | -------------------------------------------------------------------------------- /source/tv/single_element_storage.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.single_element_storage; 7 | 8 | import bounded; 9 | import std_module; 10 | 11 | namespace tv { 12 | 13 | export template 14 | union [[clang::trivial_abi]] single_element_storage trivially_relocatable_if_eligible replaceable_if_eligible { 15 | ~single_element_storage() requires bounded::trivially_destructible = default; 16 | constexpr ~single_element_storage() {} 17 | T value; 18 | }; 19 | 20 | export constexpr auto relocate_into_storage = [](auto & value) { 21 | return single_element_storage>{bounded::relocate(value)}; 22 | }; 23 | 24 | } // namespace tv 25 | -------------------------------------------------------------------------------- /source/bounded/isomorphic_to_integral.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.isomorphic_to_integral; 7 | 8 | import bounded.integral; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | export template 15 | concept isomorphic_to_integral = 16 | integral or 17 | std::is_enum_v or 18 | std::same_as; 19 | 20 | } // namespace bounded 21 | 22 | namespace { 23 | 24 | struct s { 25 | }; 26 | 27 | static_assert(bounded::isomorphic_to_integral); 28 | static_assert(bounded::isomorphic_to_integral); 29 | static_assert(bounded::isomorphic_to_integral); 30 | static_assert(!bounded::isomorphic_to_integral); 31 | 32 | } // namespace -------------------------------------------------------------------------------- /source/containers/maximum_array_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.maximum_array_size; 7 | 8 | import bounded; 9 | import numeric_traits; 10 | import std_module; 11 | 12 | namespace containers { 13 | using namespace bounded::literal; 14 | 15 | constexpr auto maximum_array_bytes = bounded::min( 16 | bounded::constant>, 17 | (1_bi << 52_bi) - 1_bi 18 | ); 19 | 20 | export template 21 | constexpr auto maximum_array_size = bounded::normalize>; 22 | 23 | export template 24 | using array_size_type = bounded::integer<0, maximum_array_size>; 25 | 26 | } // namespace containers -------------------------------------------------------------------------------- /source/bounded/integral.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.integral; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.builtin_integer; 10 | import bounded.integral_constant_of_integral; 11 | 12 | namespace bounded { 13 | 14 | export template 15 | concept integral = 16 | bounded_integer or 17 | builtin_integer or 18 | integral_constant_of_integral; 19 | 20 | } // namespace bounded 21 | 22 | namespace { 23 | 24 | enum e { 25 | }; 26 | 27 | struct s { 28 | }; 29 | 30 | static_assert(bounded::integral); 31 | static_assert(!bounded::integral); 32 | static_assert(!bounded::integral); 33 | static_assert(!bounded::integral); 34 | 35 | } // namespace -------------------------------------------------------------------------------- /source/containers/test/clear.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.clear; 11 | 12 | import containers.clear; 13 | import containers.is_empty; 14 | import containers.vector; 15 | 16 | import bounded; 17 | import bounded.test_int; 18 | 19 | static_assert([]{ 20 | auto v = containers::vector({1}); 21 | containers::clear(v); 22 | BOUNDED_ASSERT(containers::is_empty(v)); 23 | return true; 24 | }()); 25 | 26 | static_assert([]{ 27 | auto v = containers::vector(); 28 | containers::clear(v); 29 | BOUNDED_ASSERT(containers::is_empty(v)); 30 | return true; 31 | }()); -------------------------------------------------------------------------------- /source/tv/indexed_value.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module tv.indexed_value; 11 | 12 | import bounded; 13 | import std_module; 14 | 15 | namespace tv { 16 | 17 | export template 18 | struct indexed_value { 19 | constexpr explicit indexed_value(T value_): 20 | m_value(OPERATORS_FORWARD(value_)) 21 | { 22 | } 23 | constexpr auto value() const & -> auto & { 24 | return m_value; 25 | } 26 | constexpr auto value() && -> auto && { 27 | return OPERATORS_FORWARD(m_value); 28 | } 29 | static constexpr auto index = bounded::constant; 30 | 31 | private: 32 | T m_value; 33 | }; 34 | 35 | } // namespace tv 36 | -------------------------------------------------------------------------------- /source/containers/reallocation_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.reallocation_size; 7 | 8 | import bounded; 9 | import numeric_traits; 10 | 11 | using namespace bounded::literal; 12 | 13 | namespace containers { 14 | 15 | export template 16 | constexpr auto reallocation_size(Capacity const current_capacity, auto const current_size, auto const extra_elements) { 17 | return ::bounded::assume_in_range(bounded::max( 18 | bounded::integer(current_size) + bounded::integer(extra_elements), 19 | bounded::min( 20 | bounded::integer(current_capacity) * 2_bi, 21 | numeric_traits::max_value 22 | ) 23 | )); 24 | } 25 | 26 | } // namespace containers 27 | -------------------------------------------------------------------------------- /source/containers/algorithms/join.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.algorithms.join; 11 | 12 | import containers.algorithms.join_with; 13 | import containers.array; 14 | import containers.range; 15 | import containers.range_value_t; 16 | 17 | import bounded; 18 | 19 | namespace containers { 20 | using namespace bounded::literal; 21 | 22 | export template 23 | constexpr auto join(Range && r) { 24 | using value_type = containers::range_value_t>; 25 | return ::containers::join_with( 26 | OPERATORS_FORWARD(r), 27 | containers::array() 28 | ); 29 | } 30 | 31 | } // namespace containers -------------------------------------------------------------------------------- /source/bounded/test/check_in_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.check_in_range_test; 11 | 12 | import bounded.check_in_range; 13 | import bounded.integer; 14 | 15 | namespace { 16 | 17 | TEST_CASE("check_in_range", "[check_in_range]") { 18 | constexpr auto minimum = bounded::constant<0>; 19 | constexpr auto maximum = bounded::constant<10>; 20 | CHECK_THROWS(bounded::check_in_range( 21 | bounded::integer<-20, 20>(bounded::constant<20>), 22 | minimum, 23 | maximum 24 | )); 25 | CHECK_THROWS(bounded::check_in_range( 26 | bounded::integer<-6, 6>(bounded::constant<-6>), 27 | minimum, 28 | maximum 29 | )); 30 | } 31 | 32 | } // namespace -------------------------------------------------------------------------------- /source/containers/random_access_iterator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.random_access_iterator; 7 | 8 | import containers.bidirectional_iterator; 9 | import containers.forward_random_access_iterator; 10 | import containers.iter_difference_t; 11 | import containers.iterator_addable; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | // TODO: require bounded::ordered when more types support <=> 19 | export template 20 | concept random_access_iterator = 21 | bidirectional_iterator and 22 | forward_random_access_iterator and 23 | iterator_addable>; 24 | 25 | } // namespace containers 26 | -------------------------------------------------------------------------------- /source/tv/nth_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.nth_type; 7 | 8 | import std_module; 9 | 10 | namespace tv { 11 | 12 | template 13 | struct nth_type_c { 14 | using type = typename nth_type_c::type; 15 | }; 16 | template 17 | struct nth_type_c<0, T, Ts...> { 18 | using type = T; 19 | }; 20 | 21 | export template 22 | using nth_type = typename nth_type_c::type; 23 | 24 | } // namespace tv 25 | 26 | static_assert(std::same_as, int>); 27 | static_assert(std::same_as, int>); 28 | static_assert(std::same_as, long>); 29 | -------------------------------------------------------------------------------- /source/bounded/hash.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.hash; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.integer; 10 | 11 | import std_module; 12 | 13 | template 14 | struct std::hash { 15 | using argument_type = Integer; 16 | static constexpr decltype(auto) operator()(argument_type const & argument) { 17 | using underlying_type = typename argument_type::underlying_type; 18 | return hash{}(static_cast(argument)); 19 | } 20 | }; 21 | 22 | using integer = bounded::integer<0, 0>; 23 | 24 | static_assert(std::same_as< 25 | decltype(std::hash()(integer())), 26 | decltype(std::hash()(integer::underlying_type())) 27 | >); -------------------------------------------------------------------------------- /source/bounded/is_bounded_integer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.is_bounded_integer; 7 | 8 | namespace bounded { 9 | 10 | export template 11 | constexpr auto is_bounded_integer = false; 12 | 13 | template 14 | constexpr auto is_bounded_integer = is_bounded_integer; 15 | 16 | template 17 | constexpr auto is_bounded_integer = is_bounded_integer; 18 | 19 | template 20 | constexpr auto is_bounded_integer = is_bounded_integer; 21 | 22 | template 23 | constexpr auto is_bounded_integer = is_bounded_integer; 24 | 25 | template 26 | constexpr auto is_bounded_integer = is_bounded_integer; 27 | 28 | } // namespace bounded -------------------------------------------------------------------------------- /source/bounded/include/bounded/arithmetic/common_arithmetic.hpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef BOUNDED_ARITHMETIC_COMMON_ARITHMETIC_HPP 7 | #define BOUNDED_ARITHMETIC_COMMON_ARITHMETIC_HPP 8 | 9 | #include 10 | 11 | import bounded.arithmetic.increment_decrement; 12 | 13 | import operators; 14 | 15 | #define BOUNDED_COMMON_ARITHMETIC(...) \ 16 | OPERATORS_IMPORT_COMPOUND_ASSIGNMENT(__VA_ARGS__) \ 17 | __VA_ARGS__ using operators::binary::operator-; \ 18 | __VA_ARGS__ using operators::postfix::operator++; \ 19 | __VA_ARGS__ using operators::postfix::operator--; \ 20 | __VA_ARGS__ using bounded::arithmetic::operator++; \ 21 | __VA_ARGS__ using bounded::arithmetic::operator--; 22 | 23 | #endif // BOUNDED_ARITHMETIC_COMMON_ARITHMETIC_HPP -------------------------------------------------------------------------------- /source/bounded/value_to_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.value_to_function; 7 | 8 | import std_module; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | struct value_to_function { 14 | static_assert(std::is_reference_v); 15 | 16 | constexpr explicit value_to_function(T && ref) noexcept: 17 | m_ptr(std::addressof(ref)) 18 | { 19 | } 20 | 21 | constexpr auto operator()() const & noexcept -> T & { 22 | return *m_ptr; 23 | } 24 | constexpr auto operator()() const && noexcept -> T { 25 | return static_cast(*m_ptr); 26 | } 27 | 28 | private: 29 | std::remove_reference_t * m_ptr; 30 | }; 31 | 32 | template 33 | value_to_function(T &&) -> value_to_function; 34 | 35 | } // namespace bounded -------------------------------------------------------------------------------- /source/containers/algorithms/sort/rotate_one.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.rotate_one; 7 | 8 | import bounded; 9 | import std_module; 10 | import tv; 11 | 12 | namespace containers { 13 | 14 | export template 15 | constexpr auto rotate_one(T & arg, auto & ... args) { 16 | auto storage = tv::relocate_into_storage(arg); 17 | auto ref = std::reference_wrapper(arg); 18 | (..., (bounded::relocate_at(ref.get(), args), ref = args)); 19 | bounded::relocate_at(ref.get(), storage.value); 20 | } 21 | 22 | } // namespace containers 23 | 24 | static_assert([]{ 25 | int a = 0; 26 | int b = 1; 27 | int c = 2; 28 | int d = 3; 29 | ::containers::rotate_one(d, c, b, a); 30 | return a == 3 and b == 0 and c == 1 and d == 2; 31 | }()); -------------------------------------------------------------------------------- /source/bounded/comparison_builtin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.comparison_builtin; 7 | 8 | export import bounded.comparison; 9 | import bounded.bounded_integer; 10 | import bounded.builtin_integer; 11 | import bounded.integer; 12 | 13 | import std_module; 14 | 15 | namespace bounded { 16 | 17 | export constexpr auto operator<=>(bounded_integer auto const lhs, builtin_integer auto const rhs) { 18 | return lhs <=> integer(rhs); 19 | } 20 | export constexpr auto operator==(bounded_integer auto const lhs, builtin_integer auto const rhs) -> bool { 21 | return lhs == integer(rhs); 22 | } 23 | 24 | export constexpr auto operator<=>(bounded_integer auto, bool) = delete; 25 | export constexpr auto operator==(bounded_integer auto, bool) -> bool = delete; 26 | 27 | } // namespace bounded 28 | -------------------------------------------------------------------------------- /source/containers/test/is_container.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.is_container; 7 | 8 | import containers.is_container; 9 | 10 | import std_module; 11 | 12 | static_assert(containers::is_container>); 13 | static_assert(!containers::is_container &>); 14 | static_assert(containers::is_container); 15 | static_assert(!containers::is_container); 16 | static_assert(containers::is_container>); 17 | static_assert(!containers::is_container &>); 18 | static_assert(containers::is_container>); 19 | static_assert(!containers::is_container &>); 20 | static_assert(containers::is_container>); 21 | static_assert(!containers::is_container &>); -------------------------------------------------------------------------------- /source/containers/algorithms/sort/cheaply_sortable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.cheaply_sortable; 7 | 8 | import bounded; 9 | import std_module; 10 | 11 | using namespace bounded::literal; 12 | 13 | namespace containers { 14 | 15 | // Size determined experimentally, but also the size of a cache line. Maybe it 16 | // should be `std::hardware_destructive_interference_size`? 17 | // This incorrectly considers `std::string_view` cheaply_sortable. This ideally 18 | // would have something like `has_default_compare`. 19 | export template 20 | concept cheaply_sortable = 21 | std::is_trivially_copyable_v and 22 | sizeof(T) <= 64_bi and 23 | (std::same_as> or std::same_as>); 24 | 25 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/forward_iterator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.forward_iterator; 7 | 8 | import containers.iterator; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | template 16 | concept only_input_or_output_iterator = 17 | std::same_as or 18 | std::same_as; 19 | 20 | export template 21 | concept forward_iterator = 22 | iterator and 23 | bounded::copy_constructible> and 24 | // This test is needed only to support legacy copyable iterators 25 | !only_input_or_output_iterator>; 26 | 27 | } // namespace containers 28 | -------------------------------------------------------------------------------- /source/containers/test/sort/fixed_size_merge_sort.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.algorithms.sort.fixed_size_merge_sort; 7 | 8 | import containers.algorithms.sort.fixed_size_merge_sort; 9 | import containers.array; 10 | import containers.begin_end; 11 | 12 | import bounded; 13 | import std_module; 14 | 15 | using namespace bounded::literal; 16 | 17 | static_assert([]{ 18 | auto container = containers::array{0, 1}; 19 | containers::fixed_size_merge_sort(containers::begin(container), 1_bi, 1_bi, std::less()); 20 | return container == containers::array{0, 1}; 21 | }()); 22 | 23 | static_assert([]{ 24 | auto container = containers::array{1, 0}; 25 | containers::fixed_size_merge_sort(containers::begin(container), 1_bi, 1_bi, std::less()); 26 | return container == containers::array{0, 1}; 27 | }()); -------------------------------------------------------------------------------- /source/bounded/scope_fail.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.scope_fail; 7 | 8 | import bounded.scope_guard; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | export template 15 | struct scope_fail { 16 | constexpr explicit scope_fail(Function f): 17 | m_uncaught_exceptions(std::uncaught_exceptions()), 18 | m_scope_guard(std::move(f)) 19 | { 20 | } 21 | 22 | constexpr scope_fail(scope_fail && other) = default; 23 | 24 | constexpr ~scope_fail() { 25 | if (m_uncaught_exceptions == std::uncaught_exceptions()) { 26 | dismiss(); 27 | } 28 | } 29 | 30 | constexpr void dismiss() { 31 | m_scope_guard.dismiss(); 32 | } 33 | 34 | private: 35 | int m_uncaught_exceptions; 36 | scope_guard m_scope_guard; 37 | }; 38 | 39 | } // namespace bounded 40 | -------------------------------------------------------------------------------- /source/containers/test/push_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.push_back; 11 | 12 | import containers.push_back; 13 | import containers.vector; 14 | 15 | import bounded.test_int; 16 | 17 | static_assert([]{ 18 | auto v = containers::vector(); 19 | containers::push_back(v, 0); 20 | BOUNDED_ASSERT(v == containers::vector({0})); 21 | containers::push_back(v, 1); 22 | BOUNDED_ASSERT(v == containers::vector({0, 1})); 23 | containers::push_back(v, 2); 24 | BOUNDED_ASSERT(v == containers::vector({0, 1, 2})); 25 | containers::push_back(v, 3); 26 | BOUNDED_ASSERT(v == containers::vector({0, 1, 2, 3})); 27 | return true; 28 | }()); -------------------------------------------------------------------------------- /source/containers/algorithms/distance.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.distance; 7 | 8 | import containers.iter_difference_t; 9 | import containers.iterator; 10 | import containers.sentinel_for; 11 | 12 | import bounded; 13 | import std_module; 14 | 15 | namespace containers { 16 | 17 | using namespace bounded::literal; 18 | 19 | export template 20 | constexpr auto distance(InputIterator first, sentinel_for auto const last) -> iter_difference_t { 21 | if constexpr (requires { last - first; }) { 22 | return last - first; 23 | } else { 24 | auto difference = iter_difference_t(0_bi); 25 | for (; first != last; ++first) { 26 | ++difference; 27 | } 28 | return difference; 29 | } 30 | } 31 | 32 | } // namespace containers 33 | -------------------------------------------------------------------------------- /source/containers/algorithms/sort/sort_exactly_1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.sort_exactly_1; 7 | 8 | import containers.iterator; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | using namespace bounded::literal; 14 | 15 | namespace containers { 16 | 17 | // Stable 18 | // Average compares: 0 (weight 0) 19 | // Max compares: 0 20 | // Sorted compares: 0 21 | // Reversed compares: 0 22 | export template 23 | constexpr auto sort_exactly_n_in_place(Iterator, bounded::constant_t<1>, Compare) -> void { 24 | } 25 | 26 | export template 27 | constexpr auto sort_exactly_n_relocate_impl( 28 | T & x0, 29 | auto const out, 30 | Compare 31 | ) -> void { 32 | bounded::relocate_at(*out, x0); 33 | } 34 | 35 | } // namespace containers 36 | -------------------------------------------------------------------------------- /source/containers/common_iterator_functions.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.common_iterator_functions; 7 | 8 | import containers.iterator; 9 | import containers.iterator_addable; 10 | 11 | import bounded; 12 | import operators; 13 | import std_module; 14 | 15 | export import containers.common_functions; 16 | 17 | namespace containers { 18 | 19 | export template requires iterator_addable 20 | constexpr auto operator+(LHS const offset, RHS it) -> RHS { 21 | return std::move(it) + offset; 22 | } 23 | 24 | export using operators::operator+=; 25 | export using operators::operator-=; 26 | export using operators::operator++; 27 | export using bounded::operator++; 28 | export using operators::operator--; 29 | export using bounded::operator--; 30 | 31 | } // namespace containers 32 | -------------------------------------------------------------------------------- /source/containers/index_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.index_type; 7 | 8 | import containers.range_size_t; 9 | 10 | import bounded; 11 | import numeric_traits; 12 | 13 | import std_module; 14 | 15 | using namespace bounded::literal; 16 | 17 | namespace containers { 18 | 19 | template 20 | struct to_index_type_impl { 21 | using type = Size; 22 | }; 23 | 24 | template 25 | struct to_index_type_impl { 26 | using type = bounded::integer< 27 | 0, 28 | bounded::normalize - 1_bi> 29 | >; 30 | }; 31 | 32 | export template 33 | using to_index_type = typename to_index_type_impl::type; 34 | 35 | export template 36 | using index_type = to_index_type>; 37 | 38 | } // namespace containers 39 | -------------------------------------------------------------------------------- /source/containers/test/algorithms/count.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.algorithms.count; 7 | 8 | import containers.algorithms.count; 9 | import containers.array; 10 | import containers.size; 11 | 12 | import bounded; 13 | 14 | using namespace bounded::literal; 15 | 16 | constexpr auto array = containers::array({0, 3, 2, 3, 5}); 17 | 18 | static_assert(containers::count(array, 3) == 2_bi); 19 | static_assert(containers::count(array, 2) == 1_bi); 20 | static_assert(containers::count(array, 7) == 0_bi); 21 | 22 | constexpr auto false_function = [](auto const &) { return false; }; 23 | constexpr auto true_function = [](auto const &) { return true; }; 24 | 25 | static_assert(containers::count_if(array, false_function) == 0_bi); 26 | static_assert(containers::count_if(array, true_function) == containers::size(array)); 27 | -------------------------------------------------------------------------------- /source/containers/linear_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.linear_size; 11 | 12 | import containers.algorithms.distance; 13 | import containers.begin_end; 14 | import containers.range; 15 | import containers.range_size_t; 16 | import containers.size; 17 | import containers.sized_range; 18 | 19 | import bounded; 20 | 21 | namespace containers { 22 | 23 | export template 24 | constexpr auto linear_size(Range && r) { 25 | if constexpr (sized_range) { 26 | return containers::size(OPERATORS_FORWARD(r)); 27 | } else { 28 | return ::bounded::assume_in_range>(containers::distance( 29 | containers::begin(OPERATORS_FORWARD(r)), 30 | containers::end(OPERATORS_FORWARD(r)) 31 | )); 32 | } 33 | } 34 | 35 | } // namespace containers 36 | -------------------------------------------------------------------------------- /source/bounded/scope_guard.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.scope_guard; 7 | 8 | import std_module; 9 | 10 | namespace bounded { 11 | 12 | export template 13 | struct scope_guard { 14 | constexpr explicit scope_guard(Function f): 15 | m_function(std::move(f)), 16 | m_is_active(true) 17 | { 18 | } 19 | 20 | constexpr scope_guard(scope_guard && other) noexcept(std::is_nothrow_move_constructible_v): 21 | m_function(std::move(other.m_function)), 22 | m_is_active(std::exchange(other.m_is_active, false)) 23 | { 24 | } 25 | 26 | constexpr ~scope_guard() { 27 | if (m_is_active) { 28 | std::move(m_function)(); 29 | } 30 | } 31 | 32 | constexpr void dismiss() { 33 | m_is_active = false; 34 | } 35 | 36 | private: 37 | Function m_function; 38 | bool m_is_active; 39 | }; 40 | 41 | } // namespace bounded 42 | -------------------------------------------------------------------------------- /source/containers/iterator_to_sentinel.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.iterator_to_sentinel; 11 | 12 | import std_module; 13 | 14 | namespace containers { 15 | 16 | export template 17 | struct iterator_to_sentinel { 18 | private: 19 | [[no_unique_address]] Iterator m_base; 20 | public: 21 | iterator_to_sentinel() = default; 22 | 23 | constexpr explicit iterator_to_sentinel(Iterator iterator): 24 | m_base(std::move(iterator)) 25 | { 26 | } 27 | 28 | friend constexpr auto operator==(iterator_to_sentinel const &, iterator_to_sentinel const &) -> bool = default; 29 | friend constexpr auto operator==( 30 | iterator_to_sentinel const & lhs, 31 | auto const & rhs 32 | ) OPERATORS_RETURNS( 33 | lhs.m_base == rhs 34 | ) 35 | }; 36 | 37 | } // namespace containers 38 | -------------------------------------------------------------------------------- /source/containers/can_set_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.can_set_size; 7 | 8 | import containers.range; 9 | import containers.range_size_t; 10 | 11 | namespace containers { 12 | 13 | export template 14 | concept can_set_size = 15 | range and 16 | requires(Container & container, range_size_t const new_size) { 17 | container.set_size(new_size); 18 | }; 19 | 20 | } // namespace containers 21 | 22 | static_assert(!containers::can_set_size); 23 | 24 | struct range_has_set_size { 25 | auto begin() const -> int const *; 26 | auto size() const -> int; 27 | auto set_size(int) -> void; 28 | }; 29 | 30 | struct non_range_has_set_size { 31 | auto set_size(int) -> void; 32 | }; 33 | 34 | static_assert(containers::can_set_size); 35 | static_assert(!containers::can_set_size); -------------------------------------------------------------------------------- /source/containers/iter_reference_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.iter_reference_t; 7 | 8 | import containers.iterator; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | template 16 | concept has_reference_type = requires { typename Iterator::reference_type; }; 17 | 18 | template 19 | concept reference_type_matches = 20 | !has_reference_type or 21 | std::same_as; 22 | 23 | template 24 | struct iter_reference_t_impl { 25 | using type = decltype(*bounded::declval()); 26 | static_assert(reference_type_matches); 27 | }; 28 | 29 | export template 30 | using iter_reference_t = typename iter_reference_t_impl::type; 31 | 32 | } // namespace containers 33 | -------------------------------------------------------------------------------- /source/containers/test/algorithms/filter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.algorithms.filter; 7 | 8 | import containers.algorithms.compare; 9 | import containers.algorithms.filter; 10 | 11 | import containers.array; 12 | 13 | import bounded; 14 | 15 | using namespace bounded::literal; 16 | 17 | // https://github.com/llvm/llvm-project/issues/59513 18 | struct is_even { 19 | static constexpr auto operator()(auto const integer) { 20 | return integer % 2_bi == 0_bi; 21 | } 22 | }; 23 | 24 | constexpr auto check_filter() { 25 | constexpr auto source = containers::array{1_bi, 2_bi, 3_bi, 2_bi, 4_bi, 5_bi, 6_bi, 8_bi}; 26 | constexpr auto expected = containers::array{2_bi, 2_bi, 4_bi, 6_bi, 8_bi}; 27 | auto const filtered = containers::filter(source, is_even()); 28 | return containers::equal(filtered, expected); 29 | } 30 | 31 | static_assert(check_filter()); 32 | -------------------------------------------------------------------------------- /source/containers/algorithms/count.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.algorithms.count; 11 | 12 | import containers.begin_end; 13 | import containers.count_type; 14 | import containers.range; 15 | 16 | import bounded; 17 | 18 | using namespace bounded::literal; 19 | 20 | namespace containers { 21 | 22 | export template 23 | constexpr auto count_if(Range && r, auto predicate) -> count_type { 24 | auto sum = count_type(0_bi); 25 | for (decltype(auto) value : OPERATORS_FORWARD(r)) { 26 | if (predicate(OPERATORS_FORWARD(value))) { 27 | ++sum; 28 | } 29 | } 30 | return sum; 31 | } 32 | 33 | export constexpr auto count(range auto && range, auto const & value) { 34 | return ::containers::count_if(OPERATORS_FORWARD(range), bounded::equal_to(value)); 35 | } 36 | 37 | } // namespace containers 38 | -------------------------------------------------------------------------------- /source/containers/algorithms/move_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.algorithms.move_range; 11 | 12 | import containers.algorithms.transform; 13 | 14 | import containers.range; 15 | 16 | import std_module; 17 | 18 | namespace containers { 19 | 20 | struct move_transform_t { 21 | static constexpr auto operator()(auto const & it) -> decltype(auto) { 22 | using base_result = decltype(*it); 23 | using result = std::conditional_t< 24 | std::is_reference_v, 25 | std::remove_reference_t &&, 26 | base_result 27 | >; 28 | return static_cast(*it); 29 | } 30 | }; 31 | 32 | export template 33 | constexpr auto move_range(Range && r) { 34 | return containers::transform_dereference(OPERATORS_FORWARD(r), move_transform_t()); 35 | } 36 | 37 | } // namespace containers 38 | -------------------------------------------------------------------------------- /source/containers/is_empty.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.is_empty; 11 | 12 | import containers.begin_end; 13 | import containers.range; 14 | import containers.range_size_t; 15 | 16 | import bounded; 17 | import numeric_traits; 18 | import std_module; 19 | 20 | using namespace bounded::literal; 21 | 22 | namespace containers { 23 | 24 | template 25 | concept never_empty_range = numeric_traits::min_value> > 0_bi; 26 | 27 | export constexpr auto is_empty = [](range auto && r) { 28 | // The never_empty check is not needed for correctness, but allows this 29 | // function to be constexpr in more situations. 30 | return never_empty_range ? false : containers::begin(OPERATORS_FORWARD(r)) == containers::end(OPERATORS_FORWARD(r)); 31 | }; 32 | 33 | } // namespace containers 34 | -------------------------------------------------------------------------------- /source/containers/iter_value_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.iter_value_t; 7 | 8 | import containers.common_iterator_functions; 9 | import containers.iterator; 10 | 11 | import bounded; 12 | import std_module; 13 | 14 | namespace containers { 15 | 16 | template 17 | concept has_value_type = requires { typename Iterator::value_type; }; 18 | 19 | template 20 | concept value_type_matches = 21 | !has_value_type or 22 | std::same_as; 23 | 24 | template 25 | struct iter_value_t_impl { 26 | using type = std::remove_cvref_t())>; 27 | static_assert(value_type_matches); 28 | }; 29 | 30 | export template 31 | using iter_value_t = typename iter_value_t_impl::type; 32 | 33 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/test/algorithms/uninitialized.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.algorithms.uninitialized; 7 | 8 | import containers.algorithms.uninitialized; 9 | 10 | import containers.array; 11 | import containers.begin_end; 12 | import containers.subrange; 13 | 14 | import bounded; 15 | 16 | using namespace bounded::literal; 17 | 18 | constexpr auto check_relocate_backward() { 19 | auto source = containers::array{0_bi, 1_bi, 2_bi, 3_bi}; 20 | bounded::destroy(source[3_bi]); 21 | containers::uninitialized_relocate_backward( 22 | containers::subrange(containers::begin(source), containers::begin(source) + 3_bi), 23 | containers::end(source) 24 | ); 25 | bounded::construct_at(source[0_bi], [] { return 3_bi; }); 26 | constexpr auto expected = containers::array{3_bi, 0_bi, 1_bi, 2_bi}; 27 | return source == expected; 28 | } 29 | static_assert(check_relocate_backward()); 30 | -------------------------------------------------------------------------------- /containers-readme.md: -------------------------------------------------------------------------------- 1 | # Design 2 | 3 | This library implements many container types and algorithms. It follows the principles of the C++ standard library, but does not try to be perfectly backward compatible in most cases. There are some containers that have backward compatibility as a goal in `include/containers/std`. The focus is on maximum efficiency and fully decoupling data structures from algorithms. 4 | 5 | ## Containers implemented 6 | 7 | * [uninitialized_array](include/containers/uninitialized_array.hpp) 8 | * [uninitialized_dynamic_array](include/containers/uninitialized_dynamic_array.hpp) 9 | * [array](include/containers/array.hpp) 10 | * [dynamic_array](include/containers/dynamic_array.hpp) 11 | * [small_buffer_optimized_vector](include/containers/small_buffer_optimized_vector.hpp) 12 | * [stable_vector](include/containers/stable_vector.hpp) 13 | * [static_vector](include/containers/static_vector.hpp) 14 | * [vector](include/containers/vector.hpp) 15 | * [bidirectional_linked_list](include/containers/bidirectional_linked_list.hpp) 16 | * [flat_map](include/containers/flat_map.hpp) -------------------------------------------------------------------------------- /source/bounded/arithmetic/round_up_divide.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.round_up_divide; 7 | 8 | import bounded.arithmetic.operators; 9 | import bounded.bounded_integer; 10 | import bounded.integer; 11 | 12 | namespace bounded { 13 | 14 | export constexpr auto round_up_divide(bounded_integer auto const lhs, bounded_integer auto const rhs) { 15 | return (lhs + rhs - constant<1>) / rhs; 16 | } 17 | 18 | } // namespace bounded 19 | 20 | static_assert(bounded::round_up_divide(bounded::constant<1>, bounded::constant<2>) == bounded::constant<1>); 21 | static_assert(bounded::round_up_divide(bounded::constant<1>, bounded::constant<1>) == bounded::constant<1>); 22 | static_assert(bounded::round_up_divide(bounded::constant<5>, bounded::constant<1>) == bounded::constant<5>); 23 | static_assert(bounded::round_up_divide(bounded::constant<6>, bounded::constant<5>) == bounded::constant<2>); 24 | -------------------------------------------------------------------------------- /source/tv/is_valid_index.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.is_valid_index; 7 | 8 | import bounded; 9 | import std_module; 10 | 11 | using namespace bounded::literal; 12 | 13 | namespace tv { 14 | 15 | template 16 | concept matches_exactly_one_type_impl = (0_bi + ... + bounded::integer(std::same_as)) == 1_bi; 17 | 18 | export template 19 | concept matches_exactly_one_type = matches_exactly_one_type_impl, Ts...>; 20 | 21 | export template 22 | concept variant_integer_index = bounded::bounded_integer and Index::value() < size; 23 | 24 | export template 25 | concept unique_type_identifier = 26 | matches_exactly_one_type_impl or 27 | variant_integer_index; 28 | 29 | } // namespace tv 30 | -------------------------------------------------------------------------------- /source/containers/emplace_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.emplace_back; 11 | 12 | import containers.lazy_push_back; 13 | import containers.range_value_t; 14 | 15 | namespace containers { 16 | 17 | template 18 | concept member_emplace_backable = requires(Container & container, Args && ... args) { 19 | container.emplace_back(OPERATORS_FORWARD(args)...); 20 | }; 21 | 22 | export template 23 | constexpr auto & emplace_back(Container & container, Args && ... args) { 24 | if constexpr (member_emplace_backable) { 25 | return container.emplace_back(OPERATORS_FORWARD(args)...); 26 | } else { 27 | return ::containers::lazy_push_back(container, [&]{ 28 | return range_value_t(OPERATORS_FORWARD(args)...); 29 | }); 30 | } 31 | } 32 | 33 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/emplace_front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.emplace_front; 11 | 12 | import containers.lazy_push_front; 13 | import containers.range_value_t; 14 | 15 | namespace containers { 16 | 17 | template 18 | concept member_emplace_frontable = requires(Container & container, Args && ... args) { 19 | container.emplace_front(OPERATORS_FORWARD(args)...); 20 | }; 21 | 22 | export template 23 | constexpr auto & emplace_front(Container & container, Args && ... args) { 24 | if constexpr (member_emplace_frontable) { 25 | return container.emplace_front(OPERATORS_FORWARD(args)...); 26 | } else { 27 | return ::containers::lazy_push_front(container, [&]{ 28 | return range_value_t(OPERATORS_FORWARD(args)...); 29 | }); 30 | } 31 | } 32 | 33 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/to_string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.to_string; 7 | 8 | import containers.string; 9 | import containers.to_any_string; 10 | 11 | import bounded; 12 | 13 | using namespace bounded::literal; 14 | namespace containers { 15 | 16 | export constexpr auto to_string(bounded::bounded_integer auto const x) -> containers::string { 17 | return ::containers::to_any_string(x); 18 | } 19 | 20 | export constexpr auto to_string(bounded::builtin_integer auto const x) -> containers::string { 21 | return ::containers::to_any_string(x); 22 | } 23 | 24 | } // namespace containers 25 | 26 | static_assert(::containers::to_string(0_bi) == "0"); 27 | static_assert(::containers::to_string(1_bi) == "1"); 28 | static_assert(::containers::to_string(15_bi) == "15"); 29 | static_assert(::containers::to_string(-1_bi) == "-1"); 30 | static_assert(::containers::to_string(bounded::integer<-100, 100>(7_bi)) == "7"); -------------------------------------------------------------------------------- /source/containers/pop_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.pop_back; 7 | 8 | import containers.back; 9 | import containers.can_set_size; 10 | import containers.range; 11 | import containers.size; 12 | 13 | import bounded; 14 | 15 | using namespace bounded::literal; 16 | 17 | namespace containers { 18 | 19 | template 20 | concept member_pop_backable = requires (Container & container) { container.pop_back(); }; 21 | 22 | export template 23 | concept pop_backable = 24 | range and ( 25 | member_pop_backable or 26 | can_set_size 27 | ); 28 | 29 | export template 30 | constexpr auto pop_back(Container & c) -> void { 31 | if constexpr (member_pop_backable) { 32 | c.pop_back(); 33 | } else { 34 | bounded::destroy(containers::back(c)); 35 | c.set_size(containers::size(c) - 1_bi); 36 | } 37 | } 38 | 39 | } // namespace containers 40 | -------------------------------------------------------------------------------- /source/containers/test/pop_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.pop_back; 11 | 12 | import containers.algorithms.advance; 13 | import containers.algorithms.compare; 14 | import containers.begin_end; 15 | import containers.pop_back; 16 | import containers.subrange; 17 | import containers.vector; 18 | 19 | import bounded; 20 | import bounded.test_int; 21 | 22 | constexpr bool test_pop_back(containers::vector const & original) { 23 | auto copy = original; 24 | containers::pop_back(copy); 25 | BOUNDED_ASSERT(containers::equal( 26 | copy, 27 | containers::subrange(begin(original), containers::prev(end(original))) 28 | )); 29 | return true; 30 | } 31 | 32 | // Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99018 33 | static_assert([] { 34 | static_assert(test_pop_back({{1}})); 35 | static_assert(test_pop_back({{1, 2}})); 36 | return true; 37 | }()); 38 | -------------------------------------------------------------------------------- /source/containers/test/sort/to_radix_sort_key.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | 8 | import containers.algorithms.sort.is_sorted; 9 | import containers.algorithms.sort.to_radix_sort_key; 10 | 11 | import containers.array; 12 | 13 | import bounded.test_int; 14 | 15 | namespace { 16 | 17 | constexpr auto is_sorted_to_radix(auto... values) { 18 | auto const original = containers::array{values...}; 19 | CHECK(containers::is_sorted(original)); 20 | auto const converted = containers::array{containers::to_radix_sort_key(values)...}; 21 | return containers::is_sorted(converted); 22 | } 23 | 24 | TEST_CASE("to_radix_sort_key", "[to_radix_sort_key]") { 25 | constexpr int array[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 26 | CHECK(is_sorted_to_radix( 27 | array + 0, 28 | array + 1, 29 | array + 2, 30 | array + 3, 31 | array + 4, 32 | array + 5, 33 | array + 6, 34 | array + 7, 35 | array + 8 36 | )); 37 | } 38 | 39 | } // namespace 40 | -------------------------------------------------------------------------------- /source/containers/default_begin_end_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.default_begin_end_size; 11 | 12 | import containers.begin_end; 13 | import containers.range; 14 | import containers.size; 15 | import containers.sized_range; 16 | 17 | namespace containers { 18 | 19 | export struct default_begin_end_size { 20 | static constexpr auto get_begin(range auto && range) -> decltype(auto) { 21 | return containers::begin(OPERATORS_FORWARD(range)); 22 | } 23 | 24 | static constexpr auto get_end(range auto && range) -> decltype(auto) { 25 | return containers::end(OPERATORS_FORWARD(range)); 26 | } 27 | 28 | static constexpr auto get_size(sized_range auto const & range) { 29 | return containers::size(range); 30 | } 31 | template requires requires { Range::size(); } 32 | static constexpr auto get_size() { 33 | return Range::size(); 34 | } 35 | }; 36 | 37 | } // namespace containers 38 | -------------------------------------------------------------------------------- /source/containers/test/string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #include 7 | 8 | import containers.test.test_reserve_and_capacity; 9 | import containers.test.test_sequence_container; 10 | import containers.test.test_set_size; 11 | import containers.size; 12 | import containers.string; 13 | 14 | import bounded; 15 | 16 | namespace { 17 | 18 | auto check_equal(std::string_view const input) { 19 | auto const output = containers::string(input); 20 | CHECK(output == input); 21 | CHECK(containers::size(output) == containers::size(input)); 22 | } 23 | 24 | TEST_CASE("string", "[string]") { 25 | static_assert(bounded::default_constructible); 26 | containers_test::test_sequence_container(); 27 | containers_test::test_reserve_and_capacity(); 28 | containers_test::test_set_size(); 29 | check_equal("012345678901234567890123"); 30 | check_equal("0123456789012345678901234"); 31 | } 32 | 33 | } // namespace -------------------------------------------------------------------------------- /source/containers/shrink_to_fit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.shrink_to_fit; 7 | 8 | import containers.algorithms.uninitialized; 9 | import containers.begin_end; 10 | import containers.range; 11 | import containers.size; 12 | 13 | import bounded; 14 | import numeric_traits; 15 | import std_module; 16 | 17 | using namespace bounded::literal; 18 | 19 | namespace containers { 20 | 21 | export template 22 | constexpr auto shrink_to_fit(Container & c) { 23 | auto const s = containers::size(c); 24 | if (s == c.capacity()) { 25 | return; 26 | } 27 | constexpr auto min_capacity = numeric_traits::min_value; 28 | if constexpr (min_capacity > 0_bi) { 29 | if (c.capacity() == min_capacity) { 30 | return; 31 | } 32 | } 33 | auto temp = Container(); 34 | temp.reserve(s); 35 | containers::uninitialized_relocate_no_overlap(c, containers::begin(temp)); 36 | temp.set_size(s); 37 | c.set_size(0_bi); 38 | c = std::move(temp); 39 | } 40 | 41 | } // namespace containers 42 | -------------------------------------------------------------------------------- /source/tv/tuple_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.tuple_size; 7 | 8 | import tv.tuple; 9 | 10 | import bounded; 11 | import numeric_traits; 12 | import std_module; 13 | 14 | namespace tv { 15 | 16 | export template 17 | extern numeric_traits::incomplete tuple_size; 18 | 19 | template 20 | concept has_tuple_size = !std::same_as), numeric_traits::incomplete>; 21 | 22 | template 23 | constexpr auto tuple_size = tuple_size; 24 | 25 | template 26 | constexpr auto tuple_size = tuple_size; 27 | 28 | template 29 | constexpr auto tuple_size = tuple_size; 30 | 31 | template 32 | constexpr auto tuple_size = tuple_size; 33 | 34 | template 35 | constexpr auto tuple_size = tuple_size; 36 | 37 | template 38 | constexpr auto tuple_size> = bounded::constant; 39 | 40 | } // namespace tv 41 | -------------------------------------------------------------------------------- /source/containers/test/lazy_push_back_into_capacity.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.lazy_push_back_into_capacity; 11 | 12 | import containers.back; 13 | import containers.lazy_push_back_into_capacity; 14 | import containers.vector; 15 | 16 | import bounded; 17 | import bounded.test_int; 18 | 19 | using namespace bounded::literal; 20 | 21 | using vector = containers::vector; 22 | 23 | constexpr auto impl(vector & v, int const value, vector const & expected) -> void { 24 | auto & result = lazy_push_back_into_capacity(v, [=]{ return value; }); 25 | BOUNDED_ASSERT(&result == std::addressof(containers::back(v))); 26 | BOUNDED_ASSERT(v.capacity() == 2_bi); 27 | BOUNDED_ASSERT(v == expected); 28 | } 29 | 30 | constexpr auto test_lazy_push_back() -> bool { 31 | auto v = vector(); 32 | v.reserve(2_bi); 33 | impl(v, 3, vector({3})); 34 | impl(v, 4, vector({3, 4})); 35 | return true; 36 | } 37 | 38 | static_assert(test_lazy_push_back()); 39 | -------------------------------------------------------------------------------- /source/containers/algorithms/keyed_binary_search.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.algorithms.keyed_binary_search; 11 | 12 | import containers.algorithms.binary_search; 13 | import containers.associative_container; 14 | 15 | namespace containers { 16 | 17 | export constexpr auto keyed_lower_bound(associative_range auto && map, auto && key) { 18 | return containers::lower_bound( 19 | OPERATORS_FORWARD(map), 20 | OPERATORS_FORWARD(key), 21 | map.compare() 22 | ); 23 | } 24 | 25 | export constexpr auto keyed_upper_bound(associative_range auto && map, auto && key) { 26 | return containers::upper_bound( 27 | OPERATORS_FORWARD(map), 28 | OPERATORS_FORWARD(key), 29 | map.compare() 30 | ); 31 | } 32 | 33 | export constexpr auto keyed_equal_range(associative_range auto && map, auto && key) { 34 | return containers::equal_range( 35 | OPERATORS_FORWARD(map), 36 | OPERATORS_FORWARD(key), 37 | map.compare() 38 | ); 39 | } 40 | 41 | } // namespace containers 42 | -------------------------------------------------------------------------------- /source/tv/test/tuple_size.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.test.tuple_size; 7 | 8 | import tv.tuple; 9 | import tv.tuple_size; 10 | 11 | import bounded; 12 | import numeric_traits; 13 | import std_module; 14 | 15 | using namespace bounded::literal; 16 | 17 | static_assert(tv::tuple_size> == 0_bi); 18 | static_assert(tv::tuple_size> == 1_bi); 19 | static_assert(tv::tuple_size> == 2_bi); 20 | static_assert(tv::tuple_size const> == 0_bi); 21 | static_assert(tv::tuple_size volatile> == 0_bi); 22 | static_assert(tv::tuple_size const volatile> == 0_bi); 23 | static_assert(tv::tuple_size &> == 0_bi); 24 | static_assert(tv::tuple_size const &> == 0_bi); 25 | static_assert(tv::tuple_size &&> == 0_bi); 26 | static_assert(std::same_as< 27 | decltype(tv::tuple_size), 28 | numeric_traits::incomplete 29 | >); 30 | static_assert(std::same_as< 31 | decltype(tv::tuple_size), 32 | numeric_traits::incomplete 33 | >); 34 | -------------------------------------------------------------------------------- /source/containers/algorithms/sort/sort_exactly_2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.sort_exactly_2; 7 | 8 | import containers.algorithms.sort.relocate_in_order; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | using namespace bounded::literal; 14 | 15 | namespace containers { 16 | 17 | // Stable 18 | // Average compares: 1 (weight 1) 19 | // Max compares: 1 20 | // Sorted compares: 1 21 | // Reversed compares: 1 22 | export template 23 | constexpr auto sort_exactly_n_in_place_impl( 24 | T & x0, 25 | T & x1, 26 | auto const compare 27 | ) -> void { 28 | if (compare(x1, x0)) { 29 | std::ranges::swap(x0, x1); 30 | } 31 | } 32 | 33 | export template 34 | constexpr auto sort_exactly_n_relocate_impl( 35 | T & x0, 36 | T & x1, 37 | auto const out, 38 | auto const compare 39 | ) -> void { 40 | if (compare(x1, x0)) { 41 | ::containers::relocate_in_order(out, x1, x0); 42 | } else { 43 | ::containers::relocate_in_order(out, x0, x1); 44 | } 45 | } 46 | 47 | } // namespace containers 48 | -------------------------------------------------------------------------------- /source/containers/dereference.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.dereference; 7 | 8 | import containers.c_array; 9 | import containers.is_container; 10 | import containers.iterator_t; 11 | 12 | import bounded; 13 | import std_module; 14 | 15 | namespace containers { 16 | 17 | export template 18 | constexpr auto dereference = [](iterator_t const & it) -> decltype(auto) { 19 | if constexpr (is_container) { 20 | static_assert(std::is_lvalue_reference_v); 21 | return std::move(*it); 22 | } else { 23 | return *it; 24 | } 25 | }; 26 | 27 | } // namespace containers 28 | 29 | using namespace bounded::literal; 30 | 31 | static_assert(std::same_as< 32 | decltype(containers::dereference>({})), 33 | int && 34 | >); 35 | static_assert(std::same_as< 36 | decltype(containers::dereference const &>({})), 37 | int const & 38 | >); 39 | static_assert(std::same_as< 40 | decltype(containers::dereference &>({})), 41 | int & 42 | >); -------------------------------------------------------------------------------- /source/bounded/arithmetic/unary_plus.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.unary_plus; 7 | 8 | import bounded.arithmetic.extreme_values; 9 | import bounded.bounded_integer; 10 | import bounded.homogeneous_equals; 11 | import bounded.integer; 12 | 13 | namespace bounded { 14 | 15 | export constexpr auto operator+(bounded_integer auto const value) { 16 | return value; 17 | } 18 | 19 | } // namespace bounded 20 | 21 | namespace { 22 | 23 | static_assert(homogeneous_equals( 24 | +bounded::constant<0>, 25 | bounded::constant<0> 26 | )); 27 | static_assert(homogeneous_equals( 28 | +bounded::constant<-1>, 29 | bounded::constant<-1> 30 | )); 31 | static_assert(homogeneous_equals( 32 | +signed_max, 33 | signed_max 34 | )); 35 | static_assert(homogeneous_equals( 36 | +signed_min, 37 | signed_min 38 | )); 39 | static_assert(homogeneous_equals( 40 | +unsigned_max, 41 | unsigned_max 42 | )); 43 | 44 | constexpr auto x = bounded::integer<1, 10>(bounded::constant<9>); 45 | static_assert(homogeneous_equals( 46 | +x, 47 | x 48 | )); 49 | 50 | } // namespace -------------------------------------------------------------------------------- /source/containers/initializer_range.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.initializer_range; 7 | 8 | import containers.is_container; 9 | import containers.range; 10 | import containers.range_reference_t; 11 | import containers.range_value_t; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | template 19 | using source_range_reference_t = std::conditional_t< 20 | is_container, 21 | range_value_t &&, 22 | range_reference_t 23 | >; 24 | 25 | export template 26 | concept initializer_range = 27 | !std::is_array_v> and 28 | range and 29 | bounded::convertible_to, range_value_t>; 30 | 31 | // This avoids checking properties of an incomplete type 32 | export template 33 | concept constructor_initializer_range = 34 | !std::same_as, Target> and 35 | initializer_range; 36 | 37 | } // namespace containers 38 | -------------------------------------------------------------------------------- /source/containers/stable_vector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.stable_vector; 7 | 8 | import containers.bounded_vector; 9 | import containers.maximum_array_size; 10 | 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | // See https://probablydance.com/2013/05/13/4gb-per-vector/ 16 | // `capacity_` cannot be `array_size_type` because that would not support 17 | // incomplete types. 18 | export template capacity_> 19 | struct stable_vector : private bounded_vector { 20 | private: 21 | using base = bounded_vector; 22 | public: 23 | using base::base; 24 | friend constexpr auto swap(stable_vector & lhs, stable_vector & rhs) noexcept -> void { 25 | swap(static_cast(lhs), static_cast(rhs)); 26 | } 27 | using base::data; 28 | using base::size; 29 | using base::operator[]; 30 | using base::capacity; 31 | using base::set_size; 32 | using base::operator std::span; 33 | using base::operator std::span; 34 | }; 35 | 36 | } // namespace containers 37 | -------------------------------------------------------------------------------- /source/bounded/comparison_function_object.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.comparison_function_object; 11 | 12 | import bounded.comparison; 13 | 14 | import std_module; 15 | 16 | namespace bounded { 17 | 18 | template 19 | struct unary_equal_to { 20 | constexpr explicit unary_equal_to(Bound && bound): 21 | m_bound(OPERATORS_FORWARD(bound)) 22 | { 23 | } 24 | constexpr auto operator()(auto const & other) const { 25 | if constexpr (std::is_reference_v) { 26 | return m_bound.get() == other; 27 | } else { 28 | return m_bound == other; 29 | } 30 | } 31 | private: 32 | using storage = std::conditional_t< 33 | std::is_reference_v, 34 | std::reference_wrapper>, 35 | Bound 36 | >; 37 | storage m_bound; 38 | }; 39 | 40 | export constexpr auto equal_to() { 41 | return std::equal_to(); 42 | } 43 | export template 44 | constexpr auto equal_to(T && t) { 45 | return unary_equal_to(OPERATORS_FORWARD(t)); 46 | } 47 | 48 | } // namespace bounded 49 | -------------------------------------------------------------------------------- /source/containers/at.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.at; 11 | 12 | import containers.array; 13 | import containers.index_type; 14 | import containers.range; 15 | import containers.size; 16 | 17 | import bounded; 18 | import std_module; 19 | 20 | using namespace bounded::literal; 21 | 22 | namespace containers { 23 | 24 | export constexpr decltype(auto) at(range auto && r, auto const index) { 25 | auto const checked_index = bounded::check_in_range( 26 | bounded::integer(index), 27 | 0_bi, 28 | bounded::integer(containers::size(r)) - 1_bi 29 | ); 30 | return OPERATORS_FORWARD(r)[static_cast>(checked_index)]; 31 | } 32 | 33 | export constexpr decltype(auto) at(range auto && r, auto const index, bounded::unchecked_t) { 34 | using index_t = index_type; 35 | auto const converted = index_t(index); 36 | return OPERATORS_FORWARD(r)[converted]; 37 | } 38 | 39 | } // namespace containers 40 | 41 | static_assert(containers::at(containers::array({1, 2, 3}), 0_bi) == 1); 42 | -------------------------------------------------------------------------------- /source/containers/data.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.data; 7 | 8 | import containers.c_array; 9 | import containers.has_member_size; 10 | 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | template 16 | concept has_member_data = requires(Range r) { r.data(); }; 17 | 18 | template 19 | concept class_contiguous_range = has_member_data and has_member_size; 20 | 21 | export template 22 | concept contiguous_range = class_contiguous_range or std::is_array_v>; 23 | 24 | export constexpr auto data(class_contiguous_range auto && r) { 25 | return r.data(); 26 | } 27 | 28 | export template 29 | constexpr auto data(c_array const & a) -> T const * { 30 | return a; 31 | } 32 | export template 33 | constexpr auto data(c_array & a) -> T * { 34 | return a; 35 | } 36 | export template 37 | constexpr auto data(c_array && a) -> T * { 38 | return a; 39 | } 40 | 41 | } // namespace containers 42 | -------------------------------------------------------------------------------- /source/bounded/test/stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2015. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.stream_test; 11 | 12 | import bounded.integer; 13 | import bounded.comparison; 14 | import bounded.stream; 15 | import numeric_traits; 16 | import std_module; 17 | 18 | namespace { 19 | 20 | template 21 | auto streaming_test(auto const initial, auto const expected) { 22 | auto value = integer(initial); 23 | std::stringstream in; 24 | in << value; 25 | CHECK(in.str() == std::to_string(static_cast(initial))); 26 | std::stringstream out; 27 | out << expected; 28 | out >> value; 29 | CHECK(value == expected); 30 | } 31 | 32 | TEST_CASE("stream small", "[stream]") { 33 | streaming_test>(bounded::constant<7>, bounded::constant<0>); 34 | } 35 | 36 | TEST_CASE("stream large", "[stream]") { 37 | constexpr auto large_initial = bounded::constant / 3>; 38 | constexpr auto large_final = bounded::constant<-49>; 39 | streaming_test(large_initial, large_final); 40 | } 41 | 42 | } // namespace -------------------------------------------------------------------------------- /source/containers/key_comparison_function.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.key_comparison_function; 7 | 8 | import containers.ordered_associative_container; 9 | 10 | import std_module; 11 | 12 | namespace containers { 13 | 14 | template 15 | struct extract_key_to_compare { 16 | extract_key_to_compare() = default; 17 | explicit constexpr extract_key_to_compare(ExtractKey extract_key): 18 | m_extract_key(std::move(extract_key)) 19 | { 20 | } 21 | 22 | constexpr auto operator()(auto const & lhs, auto const & rhs) const { 23 | return m_extract_key(lhs) <=> m_extract_key(rhs); 24 | } 25 | 26 | private: 27 | [[no_unique_address]] ExtractKey m_extract_key; 28 | }; 29 | 30 | template 31 | constexpr auto always_false = false; 32 | 33 | export template 34 | constexpr auto key_comparison_function(Map const & map) { 35 | if constexpr (requires(Map const & c) { c.extract_key(); }) { 36 | return extract_key_to_compare(map.extract_key()); 37 | } else { 38 | static_assert(always_false, "Unimplemented"); 39 | } 40 | } 41 | 42 | } // namespace containers 43 | -------------------------------------------------------------------------------- /source/bounded/safe_compare.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.safe_compare; 7 | 8 | import bounded.builtin_integer; 9 | import bounded.signed_builtin; 10 | 11 | import numeric_traits; 12 | import std_module; 13 | 14 | namespace bounded { 15 | 16 | namespace { 17 | 18 | constexpr auto max_signed = numeric_traits::max_value; 19 | 20 | } // namespace 21 | 22 | export template 23 | constexpr auto safe_compare(LHS const lhs, RHS const rhs) -> std::strong_ordering { 24 | if constexpr (signed_builtin == signed_builtin) { 25 | return lhs <=> rhs; 26 | } else if constexpr (numeric_traits::max_value <= max_signed and numeric_traits::max_value <= max_signed) { 27 | return static_cast(lhs) <=> static_cast(rhs); 28 | } else if constexpr (signed_builtin) { 29 | return lhs < 0 ? std::strong_ordering::less : static_cast(lhs) <=> rhs; 30 | } else { 31 | return rhs < 0 ? std::strong_ordering::greater : lhs <=> static_cast(rhs); 32 | } 33 | } 34 | 35 | } // namespace bounded 36 | -------------------------------------------------------------------------------- /source/tv/test/transform.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.test.transform; 7 | 8 | import tv.transform; 9 | import tv.tuple; 10 | 11 | import std_module; 12 | 13 | struct { 14 | static constexpr auto operator()(float const x) { 15 | return static_cast(x + 1); 16 | } 17 | static constexpr auto operator()(float const x, float const y) { 18 | return static_cast(x + y); 19 | } 20 | static constexpr auto operator()(int const x) { 21 | return static_cast(x + 1); 22 | } 23 | static constexpr auto operator()(int const x, int const y) { 24 | return static_cast(x + y); 25 | } 26 | } constexpr increment_and_swap_types{}; 27 | 28 | template 29 | constexpr auto equal(T const & lhs, std::same_as auto const & rhs) { 30 | return lhs == rhs; 31 | } 32 | 33 | constexpr auto input_tuple = tv::tuple(0, 1.0F, 2, 3.0F, 4); 34 | 35 | static_assert(equal( 36 | tv::transform(increment_and_swap_types, input_tuple), 37 | tv::tuple(1.0F, 2, 3.0F, 4, 5.0F) 38 | )); 39 | 40 | static_assert(equal( 41 | tv::transform(increment_and_swap_types, input_tuple, input_tuple), 42 | tv::tuple(0.0F, 2, 4.0F, 6, 8.0F) 43 | )); -------------------------------------------------------------------------------- /source/bounded/index_sequence_struct.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2025. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.index_sequence_struct; 7 | 8 | import bounded.integer; 9 | import bounded.normalize; 10 | 11 | import std_module; 12 | 13 | namespace bounded { 14 | 15 | export template 16 | struct index_sequence_struct { 17 | index_sequence_struct() = default; 18 | template requires (size_ == size) 19 | constexpr explicit index_sequence_struct(bounded::constant_t) {} 20 | template 21 | static constexpr auto get() { 22 | return bounded::constant; 23 | } 24 | }; 25 | 26 | template 27 | index_sequence_struct(bounded::constant_t) -> index_sequence_struct; 28 | 29 | } // namespace bounded 30 | 31 | namespace std { 32 | 33 | template 34 | struct tuple_size> : std::integral_constant { 35 | }; 36 | 37 | template 38 | struct tuple_element> { 39 | using type = bounded::constant_t>; 40 | }; 41 | 42 | } // namespace std 43 | -------------------------------------------------------------------------------- /source/bounded/include/bounded/assert.hpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | #ifndef BOUNDED_ASSERT_HPP 7 | #define BOUNDED_ASSERT_HPP 8 | 9 | #include 10 | 11 | import bounded.constexpr_only_if; 12 | import bounded.prevent_comma; 13 | 14 | import std_module; 15 | 16 | // An expression of type `void`. This is used to allow using variadic 17 | // function-like macros to support expressions that contain commas, such as 18 | // `BOUNDED_ASSERT(f())`, but prevents expressions that look like two 19 | // arguments from being treated as a comma operator, such as 20 | // `BOUNDED_ASSERT(false, "Error message")`. 21 | #define BOUNDED_DETAIL_PREVENT_COMMA(...) \ 22 | decltype(::bounded::detail::prevent_comma(__VA_ARGS__))() 23 | 24 | #if defined NDEBUG or defined BOUNDED_NDEBUG 25 | #define BOUNDED_ASSERT(...) (std::is_constant_evaluated() ? ::bounded::detail::constexpr_only_if(__VA_ARGS__) : void()) 26 | #define BOUNDED_ASSERT_OR_ASSUME(...) [[assume(__VA_ARGS__)]] 27 | #else 28 | #define BOUNDED_ASSERT(...) (BOUNDED_DETAIL_PREVENT_COMMA(__VA_ARGS__), assert((__VA_ARGS__))) 29 | #define BOUNDED_ASSERT_OR_ASSUME BOUNDED_ASSERT 30 | #endif 31 | 32 | #endif // BOUNDED_ASSERT_HPP -------------------------------------------------------------------------------- /source/containers/test/push_front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.push_front; 11 | 12 | import containers.push_front; 13 | 14 | import containers.bidirectional_linked_list; 15 | import containers.forward_linked_list; 16 | import containers.front; 17 | import containers.lazy_push_front; 18 | import containers.range_value_t; 19 | 20 | import bounded; 21 | import bounded.test_int; 22 | import std_module; 23 | 24 | template 25 | constexpr auto test_push_front() -> bool { 26 | auto v = Container(); 27 | containers::push_front(v, 0); 28 | BOUNDED_ASSERT(v == Container({0})); 29 | containers::push_front(v, 1); 30 | BOUNDED_ASSERT(v == Container({1, 0})); 31 | containers::push_front(v, 2); 32 | BOUNDED_ASSERT(v == Container({2, 1, 0})); 33 | containers::push_front(v, 3); 34 | BOUNDED_ASSERT(v == Container({3, 2, 1, 0})); 35 | return true; 36 | } 37 | 38 | static_assert(test_push_front>()); 39 | static_assert(test_push_front>()); 40 | -------------------------------------------------------------------------------- /source/containers/test/lazy_push_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2019. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.lazy_push_back; 11 | 12 | import containers.algorithms.compare; 13 | import containers.lazy_push_back; 14 | import containers.vector; 15 | 16 | import bounded; 17 | import bounded.test_int; 18 | 19 | using namespace bounded::literal; 20 | 21 | constexpr bool test_lazy_push_back() { 22 | using vector = containers::vector; 23 | auto c = vector(); 24 | 25 | BOUNDED_ASSERT(c.capacity() == 0_bi); 26 | 27 | lazy_push_back(c, []{ return 3; }); 28 | BOUNDED_ASSERT(c.capacity() == 1_bi); 29 | BOUNDED_ASSERT(c == vector({3})); 30 | 31 | lazy_push_back(c, []{ return 4; }); 32 | BOUNDED_ASSERT(c.capacity() == 2_bi); 33 | BOUNDED_ASSERT(c == vector({3, 4})); 34 | 35 | lazy_push_back(c, []{ return 5; }); 36 | BOUNDED_ASSERT(c.capacity() == 4_bi); 37 | BOUNDED_ASSERT(c == vector({3, 4, 5})); 38 | 39 | lazy_push_back(c, []{ return 12; }); 40 | BOUNDED_ASSERT(c.capacity() == 4_bi); 41 | BOUNDED_ASSERT(c == vector({3, 4, 5, 12})); 42 | 43 | return true; 44 | } 45 | 46 | static_assert(test_lazy_push_back()); 47 | -------------------------------------------------------------------------------- /source/containers/repeat_n.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.repeat_n; 11 | 12 | import containers.algorithms.compare; 13 | import containers.algorithms.generate; 14 | import containers.array; 15 | 16 | import bounded; 17 | 18 | namespace containers { 19 | 20 | export template 21 | constexpr auto repeat_n(Size const size, T && value) { 22 | return generate_n(size, bounded::value_to_function(OPERATORS_FORWARD(value))); 23 | } 24 | 25 | export template 26 | constexpr auto repeat_default_n(Size const size) { 27 | return generate_n(size, bounded::construct); 28 | } 29 | 30 | } // namespace containers 31 | 32 | using namespace bounded::literal; 33 | 34 | static_assert(containers::equal(containers::repeat_default_n(0_bi), containers::array{})); 35 | static_assert(containers::equal(containers::repeat_default_n(5_bi), containers::array{0, 0, 0, 0, 0})); 36 | static_assert(containers::equal(containers::repeat_n(0_bi, 3), containers::array{})); 37 | static_assert(containers::equal(containers::repeat_n(2_bi, 3), containers::array{3, 3})); -------------------------------------------------------------------------------- /source/tv/test/is_valid_index.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.test.is_valid_index; 7 | 8 | import tv.is_valid_index; 9 | 10 | import bounded; 11 | 12 | namespace { 13 | 14 | template 15 | concept check_type_index = 16 | tv::matches_exactly_one_type and 17 | tv::unique_type_identifier, Ts...>; 18 | 19 | template 20 | concept check_integer_index = 21 | tv::variant_integer_index and 22 | tv::unique_type_identifier; 23 | 24 | static_assert(!check_type_index); 25 | static_assert(check_type_index); 26 | static_assert(!check_type_index); 27 | static_assert(check_type_index); 28 | static_assert(!check_type_index); 29 | 30 | static_assert(!check_integer_index>); 31 | static_assert(check_integer_index, int>); 32 | static_assert(!check_integer_index, int>); 33 | static_assert(check_integer_index, int, short>); 34 | static_assert(check_integer_index, int, int>); 35 | 36 | } // namespace -------------------------------------------------------------------------------- /source/tv/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright David Stone 2024. 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | add_library(tv STATIC) 7 | 8 | target_link_libraries(tv 9 | PUBLIC 10 | bounded 11 | std_module 12 | strict_defaults_interface 13 | PRIVATE 14 | strict_defaults 15 | ) 16 | 17 | target_sources(tv PUBLIC 18 | FILE_SET CXX_MODULES 19 | BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" 20 | FILES 21 | get_index.cpp 22 | indexed_value.cpp 23 | insert.cpp 24 | is_valid_index.cpp 25 | none.cpp 26 | nth_type.cpp 27 | optional.cpp 28 | overload.cpp 29 | single_element_storage.cpp 30 | transform.cpp 31 | tuple.cpp 32 | tuple_cat.cpp 33 | tuple_size.cpp 34 | tv.cpp 35 | variadic_union.cpp 36 | variant.cpp 37 | variant_index.cpp 38 | visit.cpp 39 | ) 40 | 41 | add_library(tv_test) 42 | 43 | target_link_libraries(tv_test 44 | PRIVATE 45 | bounded 46 | std_module 47 | strict_defaults 48 | tv 49 | ) 50 | 51 | target_sources(tv_test PRIVATE 52 | FILE_SET CXX_MODULES 53 | BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" 54 | FILES 55 | test/is_valid_index.cpp 56 | test/optional.cpp 57 | test/transform.cpp 58 | test/tuple.cpp 59 | test/tuple_cat.cpp 60 | test/tuple_size.cpp 61 | test/variant.cpp 62 | test/visit.cpp 63 | ) 64 | -------------------------------------------------------------------------------- /source/bounded/safe_equal.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.safe_equal; 7 | 8 | import bounded.builtin_integer; 9 | import bounded.signed_builtin; 10 | 11 | import numeric_traits; 12 | import std_module; 13 | 14 | namespace bounded { 15 | 16 | namespace { 17 | 18 | constexpr auto max_signed = numeric_traits::max_value; 19 | 20 | } // namespace 21 | 22 | export template 23 | constexpr auto safe_equal(LHS const lhs, RHS const rhs) -> bool { 24 | if constexpr (signed_builtin == signed_builtin) { 25 | return lhs == rhs; 26 | } else if constexpr (numeric_traits::max_value <= max_signed and numeric_traits::max_value <= max_signed) { 27 | return static_cast(lhs) == static_cast(rhs); 28 | } else if constexpr (signed_builtin) { 29 | static_assert(std::same_as); 30 | return lhs >= 0 and static_cast(lhs) == rhs; 31 | } else { 32 | static_assert(std::same_as); 33 | return rhs >= 0 and lhs == static_cast(rhs); 34 | } 35 | } 36 | 37 | } // namespace bounded 38 | -------------------------------------------------------------------------------- /source/containers/test/sort/test_sort.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.sort.test_sort; 7 | 8 | import containers.test.sort.sort_test_data; 9 | 10 | import containers.algorithms.all_any_none; 11 | import containers.algorithms.compare; 12 | 13 | import containers.range; 14 | import containers.range_value_t; 15 | import containers.subrange; 16 | import containers.uninitialized_array; 17 | 18 | import std_module; 19 | 20 | namespace containers_test { 21 | 22 | export constexpr auto test_sort(containers::range auto range, auto function) -> bool { 23 | return containers::all(range, [&](auto element) { 24 | function(element.input); 25 | return element.input == element.expected; 26 | }); 27 | } 28 | 29 | export constexpr auto test_sort_relocate(containers::range auto range, auto function) -> bool { 30 | return containers::all(range, [&](sort_test_data element) { 31 | auto buffer = containers::uninitialized_array, Container::size()>(); 32 | function(element.input, buffer); 33 | return containers::equal(containers::subrange(buffer.data(), buffer.size()), element.expected); 34 | }); 35 | } 36 | 37 | } // namespace containers_test -------------------------------------------------------------------------------- /source/containers/algorithms/sort/dereference_all.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.dereference_all; 7 | 8 | import containers.array; 9 | import containers.iter_value_t; 10 | 11 | import bounded; 12 | import std_module; 13 | export import tv; 14 | 15 | namespace containers { 16 | 17 | export template 18 | using element_refs = containers::array, size>; 19 | 20 | export template 21 | constexpr auto dereference_all(Iterator it, auto const size) { 22 | auto const [...indexes] = bounded::index_sequence_struct(size); 23 | using value_type = iter_value_t; 24 | using elements_t = element_refs; 25 | struct result_t { 26 | elements_t elements; 27 | Iterator last; 28 | }; 29 | // Must use brace initialization for guaranteed evaluation order. Uses a 30 | // tuple instead of an array (even though all types are the same) 31 | // because we cannot have arrays of references. Cannot use CTAD because 32 | // we want to deduce references for the values. 33 | return result_t{ 34 | elements_t{(static_cast(indexes), *it++)...}, 35 | std::move(it) 36 | }; 37 | } 38 | 39 | } // namespace containers 40 | -------------------------------------------------------------------------------- /source/bounded/construct.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module bounded.construct; 11 | 12 | import bounded.concepts; 13 | 14 | import std_module; 15 | 16 | namespace bounded { 17 | 18 | // TODO: Use lambda https://github.com/llvm/llvm-project/issues/59513 19 | template 20 | struct construct_t { 21 | template requires constructible_from 22 | static constexpr auto operator()(Args && ... args) noexcept(std::is_nothrow_constructible_v) -> T { 23 | return T(OPERATORS_FORWARD(args)...); 24 | } 25 | }; 26 | export template 27 | constexpr auto construct = construct_t(); 28 | 29 | } // namespace bounded 30 | 31 | namespace { 32 | 33 | static_assert(bounded::construct() == 0); 34 | static_assert(bounded::construct(2) == 2); 35 | static_assert(noexcept(bounded::construct())); 36 | 37 | struct not_noexcept { 38 | not_noexcept() {} 39 | }; 40 | 41 | static_assert(!noexcept(bounded::construct())); 42 | 43 | struct convert_to_int_throws { 44 | operator int() const; 45 | }; 46 | 47 | static_assert(!noexcept(bounded::construct(convert_to_int_throws()))); 48 | 49 | } // namespace -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /source/containers/test/algorithms/adjacent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.algorithms.adjacent; 7 | 8 | import containers.algorithms.adjacent; 9 | import containers.algorithms.compare; 10 | 11 | import containers.array; 12 | 13 | import bounded; 14 | import tv; 15 | 16 | using namespace bounded::literal; 17 | 18 | static_assert(containers::equal( 19 | containers::adjacent(containers::array(), 1_bi), 20 | containers::array, 0_bi>() 21 | )); 22 | static_assert(containers::equal( 23 | containers::adjacent(containers::array({1}), 1_bi), 24 | containers::array({tv::tuple(1)}) 25 | )); 26 | static_assert(containers::equal( 27 | containers::adjacent(containers::array({1}), 2_bi), 28 | containers::array, 0_bi>() 29 | )); 30 | static_assert(containers::equal( 31 | containers::adjacent(containers::array({1, 2}), 1_bi), 32 | containers::array({tv::tuple(1), tv::tuple(2)}) 33 | )); 34 | static_assert(containers::equal( 35 | containers::adjacent(containers::array({1, 2}), 2_bi), 36 | containers::array({tv::tuple(1, 2)}) 37 | )); 38 | static_assert(containers::equal( 39 | containers::adjacent(containers::array({1, 2}), 3_bi), 40 | containers::array, 0_bi>() 41 | )); 42 | -------------------------------------------------------------------------------- /source/bounded/relocate.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.relocate; 7 | 8 | import bounded.construct_at; 9 | import bounded.destroy; 10 | import bounded.non_const; 11 | 12 | import std_module; 13 | 14 | namespace bounded_relocate_adl_detail { 15 | 16 | template 17 | constexpr auto relocate(T & ref) noexcept -> T { 18 | static_assert(std::is_nothrow_move_constructible_v, "Please provide a noexcept relocate overload for your type or mark its move constructor noexcept."); 19 | static_assert(std::is_nothrow_destructible_v, "Do not mark your destructor as noexcept(false)"); 20 | auto result = std::move(ref); 21 | bounded::destroy(ref); 22 | return result; 23 | } 24 | 25 | constexpr auto relocate_impl(auto & ref) noexcept { 26 | return relocate(ref); 27 | } 28 | 29 | } // namespace relocate_adl_detail 30 | namespace bounded { 31 | 32 | export constexpr auto relocate = [](non_const auto & ref) noexcept { 33 | return ::bounded_relocate_adl_detail::relocate_impl(ref); 34 | }; 35 | 36 | export constexpr auto relocate_at = [](non_const auto & destination, non_const auto & source) noexcept -> auto & { 37 | return bounded::construct_at(destination, [&] { return bounded::relocate(source); }); 38 | }; 39 | 40 | } // namespace bounded 41 | -------------------------------------------------------------------------------- /source/containers/iterator_category_base.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | export module containers.iterator_category_base; 9 | 10 | import bounded; 11 | import std_module; 12 | 13 | namespace containers { 14 | 15 | template 16 | concept has_iterator_category = requires { 17 | typename T::iterator_category; 18 | }; 19 | 20 | export template 21 | struct iterator_category_base { 22 | }; 23 | 24 | template 25 | struct iterator_category_base { 26 | using iterator_category = typename Iterator::iterator_category; 27 | }; 28 | 29 | template requires(!bounded::convertible_to) 30 | struct iterator_category_base { 31 | using iterator_category = typename Iterator::iterator_category; 32 | 33 | iterator_category_base() = default; 34 | iterator_category_base(iterator_category_base &&) = default; 35 | iterator_category_base(iterator_category_base const &) = delete; 36 | auto operator=(iterator_category_base &&) -> iterator_category_base & = default; 37 | auto operator=(iterator_category_base const &) -> iterator_category_base & = delete; 38 | }; 39 | 40 | } // namespace containers 41 | -------------------------------------------------------------------------------- /source/containers/test/lazy_push_front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.test.lazy_push_front; 11 | 12 | import containers.bidirectional_linked_list; 13 | import containers.forward_linked_list; 14 | import containers.lazy_push_front; 15 | 16 | import bounded; 17 | import bounded.test_int; 18 | 19 | using namespace bounded::literal; 20 | 21 | template 22 | constexpr auto test_lazy_push_front() -> bool { 23 | auto c = Container(); 24 | 25 | containers::lazy_push_front(c, bounded::value_to_function(3)); 26 | BOUNDED_ASSERT(c == Container({3})); 27 | 28 | containers::lazy_push_front(c, bounded::value_to_function(4)); 29 | BOUNDED_ASSERT(c == Container({4, 3})); 30 | 31 | containers::lazy_push_front(c, bounded::value_to_function(5)); 32 | BOUNDED_ASSERT(c == Container({5, 4, 3})); 33 | 34 | containers::lazy_push_front(c, bounded::value_to_function(12)); 35 | BOUNDED_ASSERT(c == Container({12, 5, 4, 3})); 36 | 37 | return true; 38 | } 39 | 40 | static_assert(test_lazy_push_front>()); 41 | static_assert(test_lazy_push_front>()); -------------------------------------------------------------------------------- /source/containers/test/push_back_into_capacity.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | #include 10 | 11 | export module containers.test.push_back_into_capacity; 12 | 13 | import containers.back; 14 | import containers.push_back_into_capacity; 15 | import containers.vector; 16 | 17 | import bounded; 18 | import bounded.test_int; 19 | 20 | using namespace bounded::literal; 21 | 22 | using vector = containers::vector; 23 | 24 | constexpr auto impl(vector & v, auto && value, vector const & expected) -> void { 25 | auto & result = push_back_into_capacity(v, OPERATORS_FORWARD(value)); 26 | BOUNDED_ASSERT(&result == std::addressof(containers::back(v))); 27 | BOUNDED_ASSERT(v.capacity() == 2_bi); 28 | BOUNDED_ASSERT(v == expected); 29 | } 30 | 31 | static_assert([]{ 32 | auto v = vector(); 33 | v.reserve(2_bi); 34 | impl(v, 3, vector({3})); 35 | impl(v, 4, vector({3, 4})); 36 | return true; 37 | }()); 38 | 39 | static_assert([]{ 40 | auto v = vector(); 41 | v.reserve(2_bi); 42 | auto const three = bounded_test::integer(3); 43 | impl(v, three, vector({3})); 44 | auto const four = bounded_test::integer(4); 45 | impl(v, four, vector({3, 4})); 46 | return true; 47 | }()); 48 | -------------------------------------------------------------------------------- /source/containers/is_container.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.is_container; 7 | 8 | import containers.c_array; 9 | import containers.erase_concepts; 10 | import containers.pop_back; 11 | import containers.range_reference_t; 12 | 13 | import std_module; 14 | 15 | namespace containers { 16 | 17 | template 18 | concept range_reference_t_is_reference = std::is_reference_v>; 19 | 20 | // `is_container` means that if you own a value of type `T`, you can safely move 21 | // from any subset of the elements in the range. 22 | export template 23 | constexpr auto is_container = 24 | !std::is_lvalue_reference_v and 25 | range_reference_t_is_reference and ( 26 | pop_backable or 27 | pop_frontable or 28 | erasable 29 | ); 30 | 31 | template 32 | constexpr auto is_container> = true; 33 | 34 | template 35 | constexpr auto is_container> = true; 36 | 37 | } // namespace containers 38 | 39 | static_assert(!containers::is_container); 40 | static_assert(!containers::is_container); 41 | static_assert(!containers::is_container>); 42 | static_assert(!containers::is_container); -------------------------------------------------------------------------------- /source/tv/transform.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module tv.transform; 11 | 12 | import tv.tuple; 13 | import tv.tuple_size; 14 | 15 | import bounded; 16 | import std_module; 17 | 18 | using namespace bounded::literal; 19 | 20 | namespace tv { 21 | 22 | template 23 | constexpr auto all_tuple_sizes_equal = true; 24 | 25 | template 26 | constexpr auto all_tuple_sizes_equal = (... and (tuple_size == tuple_size)); 27 | 28 | template 29 | constexpr auto all_tuple_sizes = 0_bi; 30 | 31 | template 32 | constexpr auto all_tuple_sizes = tuple_size; 33 | 34 | export template 35 | constexpr auto transform(auto && function, Tuples && ... tuples) requires(all_tuple_sizes_equal) { 36 | constexpr auto size = all_tuple_sizes; 37 | auto single = [&](auto const index) -> decltype(auto) { 38 | return function(OPERATORS_FORWARD(tuples)[index]...); 39 | }; 40 | auto const [...indexes] = bounded::index_sequence_struct(size); 41 | return tuple(single(indexes)...); 42 | } 43 | 44 | } // namespace tv 45 | -------------------------------------------------------------------------------- /source/bounded/cast.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.cast; 7 | 8 | import bounded.integer; 9 | import bounded.comparison; 10 | import bounded.normalize; 11 | import bounded.safe_extreme; 12 | import bounded.unchecked; 13 | 14 | namespace bounded { 15 | 16 | export template 17 | constexpr auto increase_min(integer const & value) { 18 | return ::bounded::assume_in_range(value, constant, constant); 19 | } 20 | export template 21 | constexpr auto increase_min(integer const & value, unchecked_t) { 22 | return integer, maximum>(value, unchecked); 23 | } 24 | 25 | export template 26 | constexpr auto decrease_max(integer const & value) { 27 | return ::bounded::assume_in_range(value, constant, constant); 28 | } 29 | export template 30 | constexpr auto decrease_max(integer const & value, unchecked_t) { 31 | return integer>(value, unchecked); 32 | } 33 | 34 | } // namespace bounded 35 | -------------------------------------------------------------------------------- /source/containers/clear.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2016. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.clear; 7 | 8 | import containers.algorithms.destroy_range; 9 | import containers.can_set_size; 10 | import containers.erase_concepts; 11 | import containers.is_empty; 12 | import containers.pop_back; 13 | import containers.pop_front; 14 | 15 | import bounded; 16 | 17 | using namespace bounded::literal; 18 | 19 | namespace containers { 20 | 21 | template 22 | concept member_clearable = requires(Container & container) { container.clear(); }; 23 | 24 | template 25 | concept clearable = member_clearable or pop_backable or pop_frontable; 26 | 27 | export template 28 | constexpr auto clear(Container & container) { 29 | if constexpr (member_clearable) { 30 | container.clear(); 31 | } else if constexpr (can_set_size) { 32 | // TODO: Link to Godbolt showing better code gen 33 | containers::destroy_range(container); 34 | container.set_size(0_bi); 35 | } else { 36 | while (!containers::is_empty(container)) { 37 | if constexpr (pop_backable) { 38 | containers::pop_back(container); 39 | } else { 40 | containers::pop_front(container); 41 | } 42 | } 43 | } 44 | } 45 | 46 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/range_size_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.range_size_t; 7 | 8 | import containers.has_member_size; 9 | import containers.iter_difference_t; 10 | import containers.iterator_t; 11 | import containers.range; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | template 19 | struct size_type_impl { 20 | using type = bounded::integer< 21 | 0, 22 | bounded::builtin_max_value>> 23 | >; 24 | }; 25 | 26 | template 27 | concept has_size_type = requires { typename T::size_type; }; 28 | 29 | template requires has_size_type and has_member_size 30 | struct size_type_impl { 31 | static_assert(std::same_as().size()), typename T::size_type>); 32 | using type = typename T::size_type; 33 | }; 34 | 35 | template requires has_size_type 36 | struct size_type_impl { 37 | using type = typename T::size_type; 38 | }; 39 | 40 | template requires has_member_size 41 | struct size_type_impl { 42 | using type = decltype(bounded::declval().size()); 43 | }; 44 | 45 | export template 46 | using range_size_t = typename size_type_impl>::type; 47 | 48 | } // namespace containers 49 | -------------------------------------------------------------------------------- /source/containers/supports_lazy_insert_after.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.supports_lazy_insert_after; 7 | 8 | import containers.iterator_t; 9 | import containers.range_value_t; 10 | 11 | import bounded; 12 | import std_module; 13 | 14 | namespace containers { 15 | 16 | export template 17 | concept supports_lazy_insert_after = 18 | requires(Container container, bounded::function_ptr> make) { 19 | { container.lazy_insert_after(container.before_begin(), make) } -> std::same_as>; 20 | }; 21 | 22 | } // namespace containers 23 | 24 | struct has_lazy_insert_after { 25 | auto before_begin() const -> int const *; 26 | auto begin() const -> int const *; 27 | auto end() const -> int const *; 28 | auto lazy_insert_after(int const *, bounded::construct_function_for auto) -> int const *; 29 | }; 30 | 31 | struct has_no_lazy_insert_after { 32 | auto begin() const -> int const *; 33 | auto end() const -> int const *; 34 | }; 35 | 36 | static_assert(containers::supports_lazy_insert_after); 37 | static_assert(!containers::supports_lazy_insert_after); 38 | static_assert(!containers::supports_lazy_insert_after); 39 | static_assert(!containers::supports_lazy_insert_after); -------------------------------------------------------------------------------- /source/containers/test/dynamic_array.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.dynamic_array; 7 | 8 | import containers.test.test_sequence_container; 9 | 10 | import containers.dynamic_array; 11 | 12 | import bounded; 13 | import bounded.test_int; 14 | import std_module; 15 | 16 | static_assert(bounded::default_constructible>); 17 | static_assert(bounded::default_constructible>); 18 | 19 | static_assert(containers_test::test_sequence_container>()); 20 | static_assert(containers_test::test_sequence_container>()); 21 | 22 | static_assert(containers_test::test_sequence_container>>()); 23 | static_assert(containers_test::test_sequence_container>>()); 24 | 25 | static_assert(bounded::convertible_to const &, std::span>); 26 | static_assert(bounded::convertible_to &, std::span>); 27 | 28 | namespace { 29 | 30 | struct recursive { 31 | containers::dynamic_array> m; 32 | }; 33 | 34 | } // namespace -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Libraries 2 | 3 | This repository contains three libraries. They are implemented primarily in C++ modules, so there are no header files except for those providing macro definitions. 4 | 5 | ## bounded::integer 6 | 7 | You can read the [documentation](bounded-readme.md) and view the [headers](include/bounded) and [sources](source/bounded). This library handles integer types with compile-time bounds on the range -- `bounded::integer<1, 10>` is an integer between 1 and 10. Arithmetic operations automatically expand these bounds, so programs without explicit casts or assignment are guaranteed to have no integer overflows. 8 | 9 | ## tv 10 | 11 | This provides `tv::tuple`, `tv::variant`, and `tv::optional`. You can view the [sources](source/tv). Documentation should be added eventually. 12 | 13 | ## containers 14 | 15 | You can read the [documentation](containers-readme.md) and view the [sources](source/containers). This library implements many container types and algorithms. It follows the principles of the C++ standard library, but does not try to be perfectly backward compatible in most cases. The focus is on maximum efficiency and fully decoupling data structures from algorithms. 16 | 17 | There are some [containers that have backward compatibility as a goal](source/containers/std/) in `namespace std_containers` -- currently `std_containers::vector` and `std_containers::list`. 18 | 19 | ## Getting the code 20 | 21 | * `git submodule update --init` will check out any necessary dependencies 22 | * Configure with cmake 3.27.6+ 23 | * Build with clang 19+ -------------------------------------------------------------------------------- /source/containers/emplace_back_into_capacity.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.emplace_back_into_capacity; 11 | 12 | import containers.is_container; 13 | import containers.lazy_push_back_into_capacity; 14 | import containers.range_value_t; 15 | 16 | import bounded; 17 | 18 | namespace containers { 19 | 20 | template 21 | concept member_emplace_backable = requires(Container & container, Args && ... args) { 22 | container.emplace_back(OPERATORS_FORWARD(args)...); 23 | }; 24 | 25 | export template 26 | concept can_emplace_back_into_capacity = is_container and (can_lazy_push_back_into_capacity or member_emplace_backable); 27 | 28 | export template 29 | requires bounded::constructible_from, Args...> 30 | constexpr auto emplace_back_into_capacity(Container & container, Args && ... args) -> auto & { 31 | if constexpr (can_lazy_push_back_into_capacity) { 32 | return ::containers::lazy_push_back_into_capacity(container, [&]{ 33 | return range_value_t(OPERATORS_FORWARD(args)...); 34 | }); 35 | } else { 36 | return container.emplace_back(OPERATORS_FORWARD(args)...); 37 | } 38 | } 39 | 40 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/member_assign.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.member_assign; 11 | 12 | import containers.begin_end; 13 | 14 | namespace containers { 15 | 16 | template 17 | concept member_range_assignable = requires(Target & target, Source && source) { 18 | target.assign(OPERATORS_FORWARD(source)); 19 | }; 20 | 21 | template 22 | concept member_iterator_assignable = requires(Target & target, Source && source) { 23 | target.assign(containers::begin(OPERATORS_FORWARD(source)), containers::end(OPERATORS_FORWARD(source))); 24 | }; 25 | 26 | export template 27 | concept member_assignable = member_range_assignable or member_iterator_assignable; 28 | 29 | export template 30 | constexpr auto member_assign(Target & target, Source && source) -> void { 31 | if constexpr (member_range_assignable) { 32 | target.assign(OPERATORS_FORWARD(source)); 33 | } else { 34 | static_assert(member_iterator_assignable); 35 | // TODO: Reserve for sized forward input ranges 36 | target.assign(containers::begin(OPERATORS_FORWARD(source)), containers::end(OPERATORS_FORWARD(source))); 37 | } 38 | }; 39 | 40 | } // namespace containers 41 | -------------------------------------------------------------------------------- /source/containers/lazy_push_front.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.lazy_push_front; 11 | 12 | import containers.algorithms.splice; 13 | import containers.begin_end; 14 | import containers.front; 15 | import containers.lazy_push_back; 16 | import containers.range_value_t; 17 | import containers.splicable; 18 | import containers.supports_lazy_insert_after; 19 | 20 | import bounded; 21 | 22 | namespace containers { 23 | 24 | export template 25 | concept lazy_push_frontable = 26 | supports_lazy_insert_after or 27 | (bounded::default_constructible and lazy_push_backable and splicable); 28 | 29 | 30 | export template 31 | constexpr auto lazy_push_front( 32 | Container & container, 33 | bounded::construct_function_for> auto && constructor 34 | ) -> auto & { 35 | if constexpr (supports_lazy_insert_after) { 36 | return *container.lazy_insert_after(container.before_begin(), OPERATORS_FORWARD(constructor)); 37 | } else { 38 | auto temp = Container(); 39 | ::containers::lazy_push_back(temp, OPERATORS_FORWARD(constructor)); 40 | ::containers::splice(container, containers::begin(container), temp); 41 | return containers::front(container); 42 | } 43 | } 44 | 45 | } // namespace containers 46 | -------------------------------------------------------------------------------- /source/containers/to_any_string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.to_any_string; 7 | 8 | import containers.algorithms.reverse; 9 | 10 | import containers.push_back; 11 | 12 | import bounded; 13 | import numeric_traits; 14 | import std_module; 15 | 16 | using namespace bounded::literal; 17 | namespace containers { 18 | 19 | template 20 | constexpr auto to_any_string_impl(bounded::bounded_integer auto x, bool const include_minus) -> Result { 21 | auto result = Result(); 22 | do { 23 | ::containers::push_back(result, static_cast(x % 10_bi + bounded::constant<'0'>)); 24 | x /= 10_bi; 25 | } while (x > 0_bi); 26 | if (include_minus) { 27 | ::containers::push_back(result, '-'); 28 | } 29 | ::containers::reverse(result); 30 | return result; 31 | } 32 | 33 | template 34 | constexpr auto include_zero(T const x) { 35 | return bounded::integer<0, bounded::builtin_max_value>(x); 36 | } 37 | 38 | export template 39 | constexpr auto to_any_string(bounded::bounded_integer auto const x) -> Result { 40 | return ::containers::to_any_string_impl(::containers::include_zero(bounded::abs(x)), x < 0_bi); 41 | } 42 | 43 | export template 44 | constexpr auto to_any_string(bounded::builtin_integer auto const x) -> Result { 45 | return containers::to_any_string(bounded::integer(x)); 46 | } 47 | 48 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/default_adapt_traits.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.default_adapt_traits; 11 | 12 | import containers.common_iterator_functions; 13 | import containers.iterator; 14 | 15 | import bounded; 16 | import std_module; 17 | 18 | namespace containers { 19 | 20 | export struct default_dereference { 21 | static constexpr decltype(auto) dereference(iterator auto const & it) { 22 | return *it; 23 | } 24 | }; 25 | 26 | export struct default_add { 27 | static constexpr auto add(iterator auto it, auto const & offset) OPERATORS_RETURNS( 28 | std::move(it) + offset 29 | ) 30 | static constexpr auto add(iterator auto it, bounded::constant_t<1>) { 31 | ++it; 32 | return it; 33 | } 34 | }; 35 | 36 | export struct default_subtract { 37 | static constexpr auto subtract(iterator auto const & lhs, iterator auto const & rhs) OPERATORS_RETURNS( 38 | lhs - rhs 39 | ) 40 | }; 41 | 42 | export struct default_compare { 43 | template requires bounded::ordered 44 | static constexpr auto compare(LHS const & lhs, RHS const & rhs) { 45 | return lhs <=> rhs; 46 | } 47 | template requires bounded::equality_comparable 48 | static constexpr auto equal(LHS const & lhs, RHS const & rhs) { 49 | return lhs == rhs; 50 | } 51 | }; 52 | 53 | } // namespace containers 54 | -------------------------------------------------------------------------------- /source/containers/iter_difference_t.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | export module containers.iter_difference_t; 9 | 10 | import containers.subtractable; 11 | 12 | import bounded; 13 | import std_module; 14 | 15 | namespace containers { 16 | 17 | template 18 | struct iter_difference_t_impl; 19 | 20 | template 21 | concept has_difference_type = requires { typename T::difference_type; }; 22 | 23 | template requires has_difference_type and subtractable 24 | struct iter_difference_t_impl { 25 | static_assert(std::same_as() - bounded::declval()), typename T::difference_type>); 26 | using type = typename T::difference_type; 27 | }; 28 | 29 | template 30 | struct iter_difference_t_impl { 31 | using type = typename T::difference_type; 32 | }; 33 | 34 | template 35 | struct iter_difference_t_impl { 36 | using type = decltype(bounded::declval() - bounded::declval()); 37 | }; 38 | 39 | export template requires 40 | has_difference_type> or 41 | subtractable> 42 | using iter_difference_t = typename iter_difference_t_impl>::type; 43 | 44 | } // namespace containers 45 | 46 | static_assert(std::same_as, std::ptrdiff_t>); -------------------------------------------------------------------------------- /source/bounded/arithmetic/bitwise_and.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.bitwise_and; 7 | 8 | // I would prefer not to implement this, as bounded::integer is not a collection 9 | // of bits. However, many people use x & (y - 1) when they mean x % y, when y is 10 | // a power of two. For instance, gcc's implementation of std::sort 11 | 12 | import bounded.bounded_integer; 13 | import bounded.comparison; 14 | import bounded.integer; 15 | import bounded.minmax; 16 | import bounded.normalize; 17 | import bounded.unchecked; 18 | 19 | import numeric_traits; 20 | import std_module; 21 | 22 | namespace bounded { 23 | 24 | export template 25 | constexpr auto operator&(LHS const lhs, RHS const rhs) { 26 | // Assume always positive integers for now 27 | // Not the tightest possible bounds, but probably good enough for now 28 | using result_t = integer< 29 | 0, 30 | normalize, numeric_traits::max_value)> 31 | >; 32 | using common_t = typename std::common_type_t::underlying_type; 33 | return result_t( 34 | static_cast(lhs) & static_cast(rhs), 35 | unchecked 36 | ); 37 | } 38 | 39 | } // namespace bounded 40 | 41 | static_assert((bounded::constant<17> & bounded::constant<1>) == bounded::constant<1>); 42 | static_assert((bounded::constant<18> & bounded::constant<1>) == bounded::constant<0>); 43 | -------------------------------------------------------------------------------- /source/containers/vector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.vector; 7 | 8 | import containers.bounded_vector; 9 | import containers.c_array; 10 | import containers.maximum_array_size; 11 | import containers.range_value_t; 12 | 13 | import bounded; 14 | import numeric_traits; 15 | import std_module; 16 | 17 | using namespace bounded::literal; 18 | 19 | namespace containers { 20 | 21 | // `max_size` cannot be `array_size_type` because that would not support 22 | // incomplete types. 23 | export template max_size = numeric_traits::max_value>> 24 | struct vector : private bounded_vector { 25 | private: 26 | using base = bounded_vector; 27 | public: 28 | using base::base; 29 | friend constexpr auto swap(vector & lhs, vector & rhs) noexcept -> void { 30 | swap(static_cast(lhs), static_cast(rhs)); 31 | } 32 | using base::data; 33 | using base::size; 34 | using base::operator[]; 35 | using base::capacity; 36 | using base::set_size; 37 | using base::replace_empty_allocation; 38 | using base::reserve; 39 | using base::operator std::span; 40 | using base::operator std::span; 41 | }; 42 | 43 | template 44 | vector(Range &&) -> vector>>; 45 | 46 | template 47 | vector(c_array &&) -> vector; 48 | 49 | } // namespace containers 50 | -------------------------------------------------------------------------------- /source/containers/push_back.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.push_back; 7 | 8 | import containers.back; 9 | import containers.lazy_push_back; 10 | import containers.member_push_backable; 11 | import containers.range_value_t; 12 | 13 | import bounded; 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | export template 19 | concept push_backable = member_push_backable or lazy_push_backable; 20 | 21 | export template requires std::copy_constructible> 22 | constexpr decltype(auto) push_back(Container & container, range_value_t const & value) { 23 | if constexpr (member_push_backable) { 24 | container.push_back(value); 25 | return containers::back(container); 26 | } else { 27 | return ::containers::lazy_push_back( 28 | container, 29 | ::bounded::value_to_function(value) 30 | ); 31 | } 32 | } 33 | export template requires std::move_constructible> 34 | constexpr decltype(auto) push_back(Container & container, range_value_t && value) { 35 | if constexpr (member_push_backable) { 36 | container.push_back(std::move(value)); 37 | return containers::back(container); 38 | } else { 39 | return ::containers::lazy_push_back( 40 | container, 41 | ::bounded::value_to_function(std::move(value)) 42 | ); 43 | } 44 | } 45 | 46 | } // namespace containers -------------------------------------------------------------------------------- /source/containers/test/stable_vector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.stable_vector; 7 | 8 | import containers.test.test_sequence_container; 9 | import containers.test.test_set_size; 10 | 11 | import containers.index_type; 12 | import containers.stable_vector; 13 | 14 | import bounded; 15 | import bounded.test_int; 16 | import numeric_traits; 17 | 18 | using namespace bounded::literal; 19 | 20 | template 21 | using test_stable_vector = containers::stable_vector; 22 | 23 | static_assert(test_stable_vector::capacity() == 1000_bi); 24 | 25 | static_assert(bounded::default_constructible>); 26 | static_assert(bounded::default_constructible>); 27 | static_assert(containers_test::test_sequence_container>()); 28 | static_assert(containers_test::test_sequence_container>()); 29 | 30 | static_assert(containers_test::test_set_size>()); 31 | static_assert(containers_test::test_set_size>()); 32 | 33 | using index_type = containers::index_type>; 34 | static_assert(numeric_traits::min_value == 0_bi); 35 | static_assert(numeric_traits::max_value == 9_bi); 36 | 37 | namespace { 38 | 39 | struct recursive { 40 | containers::stable_vector m; 41 | }; 42 | 43 | } // namespace -------------------------------------------------------------------------------- /source/bounded/arithmetic/right_shift.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.right_shift; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.homogeneous_equals; 10 | import bounded.integer; 11 | import bounded.normalize; 12 | import bounded.unchecked; 13 | 14 | import numeric_traits; 15 | import std_module; 16 | 17 | namespace bounded { 18 | 19 | export template 20 | constexpr auto operator>>(integer const lhs, integer const rhs) { 21 | // TODO: Broaden range 22 | using result_t = integer< 23 | normalize<(static_cast(lhs_min) >> rhs_max)>, 24 | normalize<(static_cast(lhs_max) >> rhs_min)> 25 | >; 26 | using common_t = typename std::common_type_t, integer>::underlying_type; 27 | // It is safe to use the unchecked constructor because we already know that 28 | // the result will fit in result_t. We have to cast to the intermediate 29 | // common_t in case result_t is narrower than one of the arguments. 30 | return result_t( 31 | static_cast(lhs) >> static_cast(rhs), 32 | unchecked 33 | ); 34 | } 35 | 36 | } // namespace bounded 37 | 38 | static_assert(homogeneous_equals( 39 | bounded::constant<100> >> bounded::integer<0, 50>(bounded::constant<1>), 40 | bounded::integer<0, 100>(bounded::constant<(100 >> 1)>) 41 | )); 42 | -------------------------------------------------------------------------------- /source/containers/test/vector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.test.vector; 7 | 8 | import containers.test.test_reserve_and_capacity; 9 | import containers.test.test_sequence_container; 10 | import containers.test.test_set_size; 11 | 12 | import containers.vector; 13 | 14 | import bounded; 15 | import bounded.test_int; 16 | import std_module; 17 | 18 | using namespace bounded::literal; 19 | 20 | static_assert(bounded::default_constructible>); 21 | static_assert(bounded::default_constructible>); 22 | static_assert(containers_test::test_sequence_container>()); 23 | static_assert(containers_test::test_sequence_container>()); 24 | 25 | static_assert(containers_test::test_reserve_and_capacity>()); 26 | static_assert(containers_test::test_reserve_and_capacity>()); 27 | 28 | static_assert(containers_test::test_set_size>()); 29 | static_assert(containers_test::test_set_size>()); 30 | 31 | static_assert(bounded::convertible_to const &, std::span>); 32 | static_assert(bounded::convertible_to &, std::span>); 33 | 34 | struct recursive { 35 | containers::vector m; 36 | }; 37 | -------------------------------------------------------------------------------- /source/bounded/arithmetic/left_shift.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2018. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.arithmetic.left_shift; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.homogeneous_equals; 10 | import bounded.integer; 11 | import bounded.normalize; 12 | import bounded.unchecked; 13 | 14 | import numeric_traits; 15 | import std_module; 16 | 17 | namespace bounded { 18 | 19 | export template 20 | constexpr auto operator<<(integer const lhs, integer const rhs) { 21 | // TODO: Broaden range 22 | using result_t = integer< 23 | normalize(lhs_min) << rhs_min>, 24 | normalize(lhs_max) << rhs_max> 25 | >; 26 | using common_t = typename std::common_type_t, integer>::underlying_type; 27 | // It is safe to use the unchecked constructor because we already know that 28 | // the result will fit in result_t. We have to cast to the intermediate 29 | // common_t in case result_t is narrower than one of the arguments. 30 | return result_t( 31 | static_cast(lhs) << static_cast(rhs), 32 | unchecked 33 | ); 34 | } 35 | 36 | } // namespace bounded 37 | 38 | static_assert(homogeneous_equals( 39 | bounded::integer<0, 2>(bounded::constant<1>) << bounded::integer<0, 60>(bounded::constant<3>), 40 | bounded::integer<0, bounded::normalize<(2LL << 60LL)>>(bounded::constant<(1 << 3)>) 41 | )); 42 | -------------------------------------------------------------------------------- /source/bounded/stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.stream; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.check_in_range; 10 | import bounded.integer; 11 | 12 | import std_module; 13 | 14 | namespace bounded { 15 | 16 | export template 17 | auto operator<<(std::basic_ostream & out, bounded_integer auto const x) -> std::basic_ostream & { 18 | // The unary plus applies integer promotions to x. This ensures values are 19 | // printed as integers. Without this, I could run into an issue where the 20 | // underlying type is a typedef for char / signed char / unsigned char. 21 | // This would output the value as though it were a character. 22 | return out << +x.value(); 23 | } 24 | 25 | export template 26 | auto operator>>(std::basic_istream & in, Integer & x) -> std::basic_istream & { 27 | using underlying = typename Integer::underlying_type; 28 | constexpr auto use_int = sizeof(underlying) < sizeof(int) or (sizeof(underlying) == sizeof(int) and std::signed_integral); 29 | constexpr auto use_unsigned = sizeof(underlying) == sizeof(unsigned); 30 | using intermediate = 31 | std::conditional_t>; 35 | intermediate temp; 36 | in >> temp; 37 | x = check_in_range(integer(temp)); 38 | return in; 39 | } 40 | 41 | } // namespace bounded 42 | -------------------------------------------------------------------------------- /source/bounded/comparison.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2017. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.comparison; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.builtin_min_max_value; 10 | import bounded.safe_compare; 11 | import bounded.safe_equal; 12 | 13 | import std_module; 14 | 15 | namespace bounded { 16 | 17 | export template 18 | constexpr auto operator<=>(LHS const lhs, RHS const rhs) -> std::strong_ordering { 19 | constexpr auto lhs_min = builtin_min_value; 20 | constexpr auto lhs_max = builtin_max_value; 21 | constexpr auto rhs_min = builtin_min_value; 22 | constexpr auto rhs_max = builtin_max_value; 23 | if constexpr (safe_compare(lhs_min, rhs_max) > 0) { 24 | return std::strong_ordering::greater; 25 | } else if constexpr (safe_compare(lhs_max, rhs_min) < 0) { 26 | return std::strong_ordering::less; 27 | } else { 28 | return safe_compare(lhs.value(), rhs.value()); 29 | } 30 | } 31 | 32 | export template 33 | constexpr auto operator==(LHS const lhs, RHS const rhs) -> bool { 34 | constexpr auto lhs_min = builtin_min_value; 35 | constexpr auto lhs_max = builtin_max_value; 36 | constexpr auto rhs_min = builtin_min_value; 37 | constexpr auto rhs_max = builtin_max_value; 38 | if constexpr (safe_compare(lhs_min, rhs_max) > 0 or safe_compare(lhs_max, rhs_min) < 0) { 39 | return false; 40 | } else { 41 | return safe_equal(lhs.value(), rhs.value()); 42 | } 43 | } 44 | 45 | } // namespace bounded 46 | -------------------------------------------------------------------------------- /source/tv/test/tuple_cat.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2024. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module tv.test.tuple_cat; 7 | 8 | import tv.tuple; 9 | import tv.tuple_cat; 10 | 11 | static_assert(tv::tuple_cat() == tv::tuple()); 12 | 13 | static_assert(tv::tuple_cat(tv::tuple()) == tv::tuple()); 14 | static_assert(tv::tuple_cat(tv::tuple(1)) == tv::tuple(1)); 15 | static_assert(tv::tuple_cat(tv::tuple(1, 2)) == tv::tuple(1, 2)); 16 | 17 | static_assert(tv::tuple_cat(tv::tuple(), tv::tuple()) == tv::tuple()); 18 | static_assert(tv::tuple_cat(tv::tuple(), tv::tuple(1)) == tv::tuple(1)); 19 | static_assert(tv::tuple_cat(tv::tuple(1), tv::tuple()) == tv::tuple(1)); 20 | static_assert(tv::tuple_cat(tv::tuple(1), tv::tuple(2)) == tv::tuple(1, 2)); 21 | static_assert(tv::tuple_cat(tv::tuple(1, 2), tv::tuple(3)) == tv::tuple(1, 2, 3)); 22 | static_assert(tv::tuple_cat(tv::tuple(1, 2), tv::tuple(3, 4)) == tv::tuple(1, 2, 3, 4)); 23 | 24 | static_assert(tv::tuple_cat(tv::tuple(), tv::tuple(), tv::tuple()) == tv::tuple()); 25 | static_assert(tv::tuple_cat(tv::tuple(1), tv::tuple(), tv::tuple()) == tv::tuple(1)); 26 | static_assert(tv::tuple_cat(tv::tuple(), tv::tuple(1), tv::tuple()) == tv::tuple(1)); 27 | static_assert(tv::tuple_cat(tv::tuple(), tv::tuple(), tv::tuple(1)) == tv::tuple(1)); 28 | static_assert(tv::tuple_cat(tv::tuple(1), tv::tuple(), tv::tuple(2)) == tv::tuple(1, 2)); 29 | static_assert(tv::tuple_cat(tv::tuple(1), tv::tuple(2), tv::tuple(3)) == tv::tuple(1, 2, 3)); 30 | static_assert(tv::tuple_cat(tv::tuple(1, 2), tv::tuple(3), tv::tuple()) == tv::tuple(1, 2, 3)); 31 | -------------------------------------------------------------------------------- /source/containers/algorithms/sort/fixed_size_merge_sort.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.algorithms.sort.fixed_size_merge_sort; 7 | 8 | import containers.algorithms.sort.sort_exactly_n; 9 | 10 | import containers.algorithms.uninitialized; 11 | 12 | import containers.subrange; 13 | import containers.uninitialized_array; 14 | 15 | import bounded; 16 | import std_module; 17 | 18 | using namespace bounded::literal; 19 | namespace containers { 20 | 21 | export constexpr auto fixed_size_merge_sort(auto it, auto const size1, auto const size2, auto const compare) -> void { 22 | static_assert(size1 <= size2); 23 | static_assert(size1 > 0_bi); 24 | static_assert(size2 > 0_bi); 25 | auto first2 = it + size1; 26 | auto const last2 = first2 + size2; 27 | ::containers::sort_exactly_n(first2, size2, compare); 28 | auto buffer = containers::uninitialized_array, size1>(); 29 | auto first1 = buffer.data(); 30 | auto const last1 = first1 + size1; 31 | ::containers::sort_exactly_n_relocate(it, size1, first1, compare); 32 | while (true) { 33 | if (compare(*first2, *first1)) { 34 | bounded::relocate_at(*it, *first2); 35 | ++first2; 36 | ++it; 37 | if (first2 == last2) { 38 | ::containers::uninitialized_relocate_no_overlap(subrange(first1, last1), it); 39 | break; 40 | } 41 | } else { 42 | bounded::relocate_at(*it, *first1); 43 | ++first1; 44 | if (first1 == last1) { 45 | break; 46 | } 47 | ++it; 48 | } 49 | } 50 | } 51 | 52 | } // namespace containers 53 | -------------------------------------------------------------------------------- /source/containers/erase_concepts.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2022. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.erase_concepts; 7 | 8 | import containers.can_set_size; 9 | import containers.has_member_before_begin; 10 | import containers.iterator_t; 11 | import containers.range; 12 | import containers.splicable; 13 | 14 | import std_module; 15 | 16 | namespace containers { 17 | 18 | export template 19 | concept member_pop_frontable = requires (Container & container) { container.pop_front(); }; 20 | 21 | export template 22 | concept member_erasable = requires(Container & container, iterator_t const it) { 23 | container.erase(it, it); 24 | }; 25 | 26 | // `erase_after` is required to be constant time 27 | export template 28 | concept has_member_erase_after = requires(T & container, iterator_t const it) { 29 | { container.erase_after(it) } -> std::same_as>; 30 | }; 31 | 32 | export template 33 | concept constant_time_erasable = splicable; 34 | 35 | export template 36 | concept pop_frontable = 37 | range and ( 38 | member_pop_frontable or 39 | constant_time_erasable or 40 | (has_member_erase_after and has_member_before_begin) 41 | ); 42 | 43 | export template 44 | concept erasable = range and ( 45 | member_erasable or 46 | splicable or 47 | can_set_size 48 | ); 49 | 50 | } // namespace containers 51 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright David Stone 2019. 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at 4 | # http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | cmake_minimum_required(VERSION 3.28 FATAL_ERROR) 7 | 8 | project(bounded_integer LANGUAGES CXX) 9 | 10 | if(NOT CMAKE_BUILD_TYPE) 11 | set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type" FORCE) 12 | endif() 13 | 14 | enable_testing() 15 | 16 | get_directory_property(has_parent PARENT_DIRECTORY) 17 | if (NOT has_parent) 18 | set(CMAKE_CXX_STANDARD 26) 19 | set(CMAKE_CXX_STANDARD_REQUIRED On) 20 | set(CMAKE_CXX_EXTENSIONS Off) 21 | 22 | add_subdirectory(dependencies/cmake_strict_defaults) 23 | add_subdirectory(dependencies/numeric-traits) 24 | add_subdirectory(dependencies/operators) 25 | add_subdirectory(dependencies/std_module) 26 | 27 | add_subdirectory(dependencies/Catch2 EXCLUDE_FROM_ALL) 28 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 29 | target_compile_options(Catch2 PUBLIC 30 | "-Wno-c2y-extensions" 31 | ) 32 | endif() 33 | 34 | set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable testing benchmark.") 35 | add_subdirectory(dependencies/benchmark EXCLUDE_FROM_ALL) 36 | get_property(benchmark_include_dirs TARGET benchmark PROPERTY INTERFACE_INCLUDE_DIRECTORIES) 37 | set_property(TARGET benchmark PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${benchmark_include_dirs}") 38 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 39 | target_compile_options(benchmark PUBLIC 40 | "-Wno-global-constructors" 41 | "-Wno-c2y-extensions" 42 | ) 43 | endif() 44 | endif() 45 | 46 | add_subdirectory(source/bounded) 47 | add_subdirectory(source/tv) 48 | add_subdirectory(source/containers) 49 | -------------------------------------------------------------------------------- /source/containers/c_array.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module containers.c_array; 7 | 8 | import std_module; 9 | 10 | namespace containers { 11 | 12 | export template 13 | using c_array = T[size]; 14 | 15 | // Using this as a parameter allows construction from `{}` to work. This is 16 | // necessary because C arrays cannot be 0 size. The recommended pattern is 17 | // ``` 18 | // template Source = empty_c_array_parameter> 19 | // constexpr container(Source) { 20 | // } 21 | // ``` 22 | // This avoids ambiguity with the move constructor in `container({})` (by making 23 | // it resolve to move constructing a default constructed container) but still 24 | // allows implicit conversions from `{}` (calls the default constructor) and 25 | // `{{}}` (calls this constructor). With constexpr function parameters, this can 26 | // be replaced with a constexpr `std::initializer_list` parameter constrained to 27 | // have a size of 0 and then `container({})` won't move construct a defaulted 28 | // constructed container. 29 | 30 | export struct empty_c_array_parameter { 31 | }; 32 | 33 | template 34 | struct possibly_empty_c_array_impl { 35 | using type = c_array; 36 | }; 37 | 38 | template 39 | struct possibly_empty_c_array_impl { 40 | using type = empty_c_array_parameter; 41 | }; 42 | 43 | export template 44 | using possibly_empty_c_array = typename possibly_empty_c_array_impl::type; 45 | 46 | } // namespace containers 47 | -------------------------------------------------------------------------------- /source/bounded/clamp.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.clamp; 7 | 8 | import bounded.bounded_integer; 9 | import bounded.integer; 10 | import bounded.integral; 11 | import bounded.minmax; 12 | 13 | import numeric_traits; 14 | 15 | namespace bounded { 16 | 17 | export constexpr auto clamp(bounded_integer auto const & value, bounded_integer auto const & minimum, bounded_integer auto const & maximum) { 18 | return min( 19 | max( 20 | value, 21 | minimum 22 | ), 23 | maximum 24 | ); 25 | } 26 | 27 | export template 28 | constexpr auto clamp(integral auto const value) { 29 | return ::bounded::clamp(bounded::integer(value), numeric_traits::min_value, numeric_traits::max_value); 30 | } 31 | 32 | } // namespace bounded 33 | 34 | constexpr auto minimum = bounded::constant<27>; 35 | constexpr auto maximum = bounded::constant<567>; 36 | static_assert( 37 | clamp(bounded::constant<20>, minimum, maximum) == minimum, 38 | "Failure to properly clamp lesser positive values." 39 | ); 40 | static_assert( 41 | clamp(bounded::constant<-25>, minimum, maximum) == minimum, 42 | "Failure to properly clamp negative values to a positive value." 43 | ); 44 | static_assert( 45 | clamp(bounded::constant<1000>, minimum, maximum) == maximum, 46 | "Failure to properly clamp greater positive values." 47 | ); 48 | static_assert( 49 | clamp(bounded::constant<2000>, minimum, maximum) == maximum, 50 | "Fail to clamp above range with a strictly greater type." 51 | ); 52 | static_assert(bounded::clamp>(20) == bounded::constant<30>); 53 | -------------------------------------------------------------------------------- /source/containers/test/assign_to_empty.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2021. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.assign_to_empty_test; 11 | 12 | import containers.assign_to_empty; 13 | import containers.data; 14 | import containers.is_empty; 15 | import containers.vector; 16 | 17 | import bounded; 18 | import bounded.test_int; 19 | 20 | using namespace bounded::literal; 21 | 22 | using non_copyable = bounded_test::non_copyable_integer; 23 | 24 | using container = containers::vector; 25 | 26 | constexpr auto test_assign(bool const same_allocation, auto make_initial, auto... additional) { 27 | auto individual_test = [&](auto do_assign) { 28 | auto c = make_initial(); 29 | BOUNDED_ASSERT(containers::is_empty(c)); 30 | auto const ptr = containers::data(c); 31 | do_assign(c); 32 | BOUNDED_ASSERT(c == container({copy_value(additional)...})); 33 | if (same_allocation) { 34 | BOUNDED_ASSERT(ptr == containers::data(c)); 35 | } 36 | }; 37 | individual_test([&](container & c) { containers::assign_to_empty(c, {copy_value(additional)...}); }); 38 | individual_test([&](container & c) { containers::assign_to_empty(c, container({copy_value(additional)...})); }); 39 | return true; 40 | } 41 | 42 | static_assert(test_assign( 43 | true, 44 | [] { return container(); } 45 | )); 46 | static_assert(test_assign( 47 | false, 48 | [] { return container(); }, 49 | non_copyable(2) 50 | )); 51 | static_assert(test_assign( 52 | true, 53 | [] { 54 | auto c = container(); 55 | c.reserve(2_bi); 56 | return c; 57 | }, 58 | non_copyable(2) 59 | )); -------------------------------------------------------------------------------- /source/containers/lookup.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | #include 11 | 12 | export module containers.lookup; 13 | 14 | import containers.algorithms.find; 15 | import containers.array; 16 | import containers.associative_container; 17 | import containers.begin_end; 18 | import containers.map_value_type; 19 | import containers.size; 20 | 21 | import bounded; 22 | import std_module; 23 | 24 | namespace containers { 25 | 26 | export template::key_type> 27 | constexpr auto lookup(Map && map, Key && key) { 28 | auto const it = map.find(OPERATORS_FORWARD(key)); 29 | return it != containers::end(map) ? 30 | std::addressof(get_mapped(*it)) : 31 | nullptr; 32 | } 33 | 34 | } // namespace containers 35 | 36 | using namespace bounded::literal; 37 | 38 | struct container { 39 | using key_type = int; 40 | using mapped_type = int; 41 | 42 | constexpr auto begin() const { 43 | return containers::begin(m_data); 44 | } 45 | constexpr auto size() const { 46 | return containers::size(m_data); 47 | } 48 | constexpr auto find(int const x) const { 49 | return containers::find_if(m_data, [=](containers::map_value_type const value) { return value.key == x; }); 50 | } 51 | 52 | containers::array, 2_bi> m_data; 53 | }; 54 | 55 | static_assert([]{ 56 | auto const map = container({1, 3}); 57 | BOUNDED_ASSERT(*containers::lookup(map, 1) == 3); 58 | BOUNDED_ASSERT(!containers::lookup(map, 2)); 59 | return true; 60 | }()); -------------------------------------------------------------------------------- /source/bounded/lazy_init.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2020. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | export module bounded.lazy_init; 7 | 8 | import bounded.concepts; 9 | 10 | import std_module; 11 | 12 | namespace bounded { 13 | 14 | export struct lazy_init_t { 15 | }; 16 | export constexpr auto lazy_init = lazy_init_t(); 17 | 18 | export template 19 | concept construct_function_for = convertible_to< 20 | std::invoke_result_t, 21 | T 22 | >; 23 | 24 | } // namespace bounded 25 | 26 | template 27 | auto function() -> T; 28 | template 29 | constexpr auto object = []{ return T(); }; 30 | 31 | static_assert(bounded::construct_function_for), void>); 32 | static_assert(bounded::construct_function_for), void>); 33 | 34 | static_assert(!bounded::construct_function_for), void>); 35 | static_assert(!bounded::construct_function_for), void>); 36 | 37 | static_assert(!bounded::construct_function_for), int>); 38 | static_assert(!bounded::construct_function_for), int>); 39 | 40 | static_assert(bounded::construct_function_for), int>); 41 | static_assert(bounded::construct_function_for), int>); 42 | 43 | static_assert(bounded::construct_function_for), short>); 44 | static_assert(bounded::construct_function_for), short>); 45 | 46 | static_assert(bounded::construct_function_for), int>); 47 | static_assert(bounded::construct_function_for), int>); 48 | -------------------------------------------------------------------------------- /source/containers/append_after.cpp: -------------------------------------------------------------------------------- 1 | // Copyright David Stone 2023. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // (See accompanying file LICENSE_1_0.txt or copy at 4 | // http://www.boost.org/LICENSE_1_0.txt) 5 | 6 | module; 7 | 8 | #include 9 | 10 | export module containers.append_after; 11 | 12 | import containers.algorithms.copy_or_relocate_from; 13 | import containers.c_array; 14 | import containers.iterator_t; 15 | import containers.range; 16 | import containers.range_value_t; 17 | import containers.supports_lazy_insert_after; 18 | 19 | import std_module; 20 | 21 | namespace containers { 22 | 23 | template 24 | constexpr auto append_after_impl(Target & target, iterator_t before_position, Source && source) -> void { 25 | ::containers::copy_or_relocate_from(OPERATORS_FORWARD(source), [&](auto make) { 26 | before_position = target.lazy_insert_after(before_position, make); 27 | }); 28 | } 29 | 30 | export template 31 | constexpr auto append_after(Target & target, iterator_t before_position, range auto && source) -> void { 32 | ::containers::append_after_impl(target, before_position, OPERATORS_FORWARD(source)); 33 | } 34 | 35 | export template 36 | constexpr auto append_after(Target &, iterator_t, empty_c_array_parameter) -> void { 37 | } 38 | export template 39 | constexpr auto append_after(Target & target, iterator_t before_position, c_array, init_size> && source) -> void { 40 | ::containers::append_after_impl(target, before_position, std::move(source)); 41 | } 42 | 43 | } // namespace containers 44 | --------------------------------------------------------------------------------