diff --git a/.github/workflows/code_testing.yaml b/.github/workflows/code_testing.yaml index f37bed7..8d5eacf 100644 --- a/.github/workflows/code_testing.yaml +++ b/.github/workflows/code_testing.yaml @@ -13,14 +13,14 @@ jobs: matrix: config: - os: ubuntu-24.04 - compiler: clang-18 + compiler: llvm-19 - os: ubuntu-24.04 - compiler: clang-19 - - os: ubuntu-24.04 - compiler: clang-20 + compiler: llvm-20 - os: ubuntu-24.04 - compiler: gcc-14 + compiler: gcc-15 + - os: ubuntu-24.04 + compiler: gcc-16 runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.compiler }}) defaults: @@ -31,21 +31,23 @@ jobs: - name: Add compiler repos uses: dice-group/cpp-conan-release-reusable-workflow/.github/actions/setup_apt@main - - name: Install CMake - uses: lukka/get-cmake@latest - with: - cmakeVersion: 3.29.3 - - - name: Install compiler - id: install_cc - uses: rlalik/setup-cpp-compiler@v1.2 + - name: Setup Cpp + uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.config.compiler }} + vcvarsall: false - - name: Configure conan - uses: dice-group/cpp-conan-release-reusable-workflow/.github/actions/configure_conan@main - with: - conan-version: 2.21.0 + cmake: 3.29.3 + ninja: true + vcpkg: false + ccache: false + clangtidy: false + conan: 2.29.0 + + cppcheck: false + + gcovr: false + opencppcoverage: false - name: add conan user run: | @@ -65,9 +67,6 @@ jobs: - name: Configure CMake run: cmake -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined" -DCMAKE_BUILD_TYPE=Debug -DWITH_SVECTOR=ON -DWITH_BOOST=ON -DBUILD_TESTING=On -DBUILD_EXAMPLES=On -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=conan_provider.cmake -G Ninja -B build . - env: - CC: ${{ steps.install_cc.outputs.cc }} - CXX: ${{ steps.install_cc.outputs.cxx }} - name: Build tests and examples working-directory: build diff --git a/.gitignore b/.gitignore index 8520d1e..3571661 100644 --- a/.gitignore +++ b/.gitignore @@ -107,7 +107,7 @@ test_package/build/ test_package/CMakeUserPresets.json /CMakeUserPresets.json /conan_provider.cmake -include/dice/template-library/version.hpp +/include/dice/template-library/version.cppm .clang-tidy .clang-format diff --git a/CMakeLists.txt b/CMakeLists.txt index 63d3772..2876ca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.28) project( dice-template-library @@ -8,7 +8,7 @@ project( HOMEPAGE_URL "https://dice-research.org/") set(POBR_VERSION 2) # Persisted Object Binary Representation -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/include/dice/template-library/version.hpp) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cppm.in ${CMAKE_CURRENT_SOURCE_DIR}/src/dice/template-library/version.cppm) option(BUILD_TESTING "build tests" OFF) option(BUILD_EXAMPLES "build examples" OFF) @@ -40,17 +40,52 @@ if (PROJECT_IS_TOP_LEVEL) endif () endif () -add_library(${PROJECT_NAME} INTERFACE) +add_library(${PROJECT_NAME} STATIC) add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -target_include_directories(${PROJECT_NAME} INTERFACE +target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES BASE_DIRS $ FILES + src/dice/template-library/dtl.cppm + src/dice/template-library/version.cppm + src/dice/template-library/channel.cppm + src/dice/template-library/flex_array.cppm + src/dice/template-library/fmt_join.cppm + src/dice/template-library/for.cppm + src/dice/template-library/format_to_ostream.cppm + src/dice/template-library/functional.cppm + src/dice/template-library/inplace_polymorphic.cppm + src/dice/template-library/integral_template_tuple.cppm + src/dice/template-library/integral_sequence.cppm + src/dice/template-library/integral_template_variant.cppm + src/dice/template-library/lazy_conditional.cppm + src/dice/template-library/limit_allocator.cppm + src/dice/template-library/mutex.cppm + src/dice/template-library/next_to_range.cppm + src/dice/template-library/opt_minmax.cppm + src/dice/template-library/ranges.cppm + src/dice/template-library/overloaded.cppm + src/dice/template-library/pointer_tag_pair.cppm + src/dice/template-library/polymorphic_allocator.cppm + src/dice/template-library/pool_allocator.cppm + src/dice/template-library/shared_mutex.cppm + src/dice/template-library/static_string.cppm + src/dice/template-library/stdint.cppm + src/dice/template-library/switch_cases.cppm + + src/dice/template-library/standard_layout_tuple.cppm + src/dice/template-library/tuple_algorithm.cppm + src/dice/template-library/type_traits.cppm + src/dice/template-library/type_list.cppm + src/dice/template-library/variant2.cppm +) + +target_include_directories(${PROJECT_NAME} PUBLIC $ ) if (WITH_SVECTOR) find_package(svector REQUIRED) - target_link_libraries(${PROJECT_NAME} INTERFACE + target_link_libraries(${PROJECT_NAME} PUBLIC svector::svector ) endif () @@ -58,7 +93,7 @@ endif () if (WITH_BOOST) find_package(Boost REQUIRED COMPONENTS) - target_link_libraries(${PROJECT_NAME} INTERFACE + target_link_libraries(${PROJECT_NAME} PUBLIC Boost::headers ) endif () @@ -68,9 +103,10 @@ set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF CXX_STANDARD_REQUIRED ON ) +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) -include(cmake/install_interface_library.cmake) -install_interface_library(${PROJECT_NAME} ${PROJECT_NAME} ${PROJECT_NAME} "include") +include(cmake/install_module_library.cmake) +install_module_library(${PROJECT_NAME} ${PROJECT_NAME} ${PROJECT_NAME} "include") if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING) include(CTest) diff --git a/cmake/install_interface_library.cmake b/cmake/install_interface_library.cmake deleted file mode 100644 index 8e0847b..0000000 --- a/cmake/install_interface_library.cmake +++ /dev/null @@ -1,40 +0,0 @@ -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -function(install_interface_library TARGET_NAME NAMESPACE LIBRARY_NAME INCLUDE_PATH) - - target_include_directories( - ${TARGET_NAME} INTERFACE $) - - set_property(TARGET ${TARGET_NAME} PROPERTY EXPORT_NAME ${LIBRARY_NAME}) - - install( - TARGETS ${TARGET_NAME} - EXPORT ${TARGET_NAME}-targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - - - write_basic_package_version_file( - "${TARGET_NAME}-config-version.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion) - - configure_package_config_file( - "${PROJECT_SOURCE_DIR}/cmake/lib-config.cmake.in" - "${PROJECT_BINARY_DIR}/${TARGET_NAME}-config.cmake" - INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - - install( - EXPORT ${TARGET_NAME}-targets - FILE ${TARGET_NAME}-targets.cmake - NAMESPACE ${NAMESPACE}:: - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - - install(FILES "${PROJECT_BINARY_DIR}/${TARGET_NAME}-config.cmake" - "${PROJECT_BINARY_DIR}/${TARGET_NAME}-config-version.cmake" - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) - - install(DIRECTORY ${PROJECT_SOURCE_DIR}/${INCLUDE_PATH}/ DESTINATION include) -endfunction() diff --git a/cmake/install_module_library.cmake b/cmake/install_module_library.cmake new file mode 100644 index 0000000..555bd83 --- /dev/null +++ b/cmake/install_module_library.cmake @@ -0,0 +1,44 @@ +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +function(install_module_library TARGET_NAME NAMESPACE LIBRARY_NAME INCLUDE_PATH) + + target_include_directories( + ${TARGET_NAME} PUBLIC $) + + set_property(TARGET ${TARGET_NAME} PROPERTY EXPORT_NAME ${LIBRARY_NAME}) + + install(TARGETS ${TARGET_NAME} ${ARGN} + EXPORT ${TARGET_NAME}-targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILE_SET CXX_MODULES DESTINATION modules + ) + + write_basic_package_version_file("${TARGET_NAME}-config-version.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY ExactVersion) + + configure_package_config_file( + "${PROJECT_SOURCE_DIR}/cmake/lib-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}-config.cmake" + INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${TARGET_NAME}/cmake) + # here we have two possibilities: either CMAKE_INSTALL_DATAROOTDIR (share) or CMAKE_INSTALL_LIBDIR (lib/lib64) + # we just have to be consistent for one target + + install( + EXPORT ${TARGET_NAME}-targets + FILE ${TARGET_NAME}-targets.cmake + NAMESPACE ${NAMESPACE}:: + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) + + install(FILES "${PROJECT_BINARY_DIR}/${TARGET_NAME}-config.cmake" + "${PROJECT_BINARY_DIR}/${TARGET_NAME}-config-version.cmake" + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake) + + install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${INCLUDE_PATH}/ + DESTINATION include + FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") +endfunction() diff --git a/cmake/version.hpp.in b/cmake/version.cppm.in similarity index 71% rename from cmake/version.hpp.in rename to cmake/version.cppm.in index 61d130f..456efe4 100644 --- a/cmake/version.hpp.in +++ b/cmake/version.cppm.in @@ -1,13 +1,10 @@ -#ifndef DICE_TEMPLATELIBRARY_VERSION_HPP -#define DICE_TEMPLATELIBRARY_VERSION_HPP - +module; #include +export module dice.template_library:version; -namespace dice::template_library { +export namespace dice::template_library { inline constexpr char name[] = "@PROJECT_NAME@"; inline constexpr char version[] = "@PROJECT_VERSION@"; inline constexpr std::array version_tuple = {@PROJECT_VERSION_MAJOR@, @PROJECT_VERSION_MINOR@, @PROJECT_VERSION_PATCH@}; inline constexpr int pobr_version = @POBR_VERSION@; ///< persisted object binary representation version } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_VERSION_HPP diff --git a/conanfile.py b/conanfile.py index 38ac7ba..7ff9149 100644 --- a/conanfile.py +++ b/conanfile.py @@ -14,7 +14,7 @@ class DiceTemplateLibrary(ConanFile): topics = "template", "template-library", "compile-time", "switch", "integral-tuple" settings = "os", "arch", "compiler", "build_type" generators = "CMakeDeps", "CMakeToolchain" - exports_sources = "include/*", "CMakeLists.txt", "cmake/*", "LICENSE" + exports_sources = "include/*", "CMakeLists.txt", "cmake/*", "LICENSE", "src/*" options = { "with_test_deps": [True, False], "with_svector": [True, False], @@ -70,18 +70,15 @@ def package_id(self): def package(self): self._configure_cmake().install() - for dir in ("lib", "res", "share"): - rmdir(self, os.path.join(self.package_folder, dir)) - copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) def package_info(self): self.cpp_info.bindirs = [] self.cpp_info.libdirs = [] - - self.cpp_info.set_property("cmake_find_mode", "both") - self.cpp_info.set_property("cmake_target_name", f"{self.name}::{self.name}") - self.cpp_info.set_property("cmake_file_name", self.name) + + self.cpp_info.libs = ["dice-template-library"] + self.cpp_info.set_property("cmake_find_mode", "none") + self.cpp_info.builddirs = ["."] if self.options.with_svector: self.cpp_info.requires += ["svector::svector"] diff --git a/examples/example_channel.cpp b/examples/example_channel.cpp index 9211fa6..eae6223 100644 --- a/examples/example_channel.cpp +++ b/examples/example_channel.cpp @@ -1,10 +1,10 @@ -#include - #include #include #include #include +#include +import dice.template_library; int main() { dice::template_library::channel chan{8}; diff --git a/examples/example_flex_array.cpp b/examples/example_flex_array.cpp index 17b67c2..bdeadf9 100644 --- a/examples/example_flex_array.cpp +++ b/examples/example_flex_array.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +import dice.template_library; + using namespace dice::template_library; // multidimensional-shape polymorphism without heap allocation diff --git a/examples/example_format_to_ostream.cpp b/examples/example_format_to_ostream.cpp index 7b6e665..43f8ec4 100644 --- a/examples/example_format_to_ostream.cpp +++ b/examples/example_format_to_ostream.cpp @@ -1,11 +1,11 @@ -// Include the overload that makes it ostreamable. -#include - #include #include #include #include +// Import the overload that makes it ostreamable. +import dice.template_library; + // A type that has no std::ostream operator<< defined struct not_ostreamable { int value; diff --git a/examples/example_inplace_polymorphic.cpp b/examples/example_inplace_polymorphic.cpp index 4618032..1b754a3 100644 --- a/examples/example_inplace_polymorphic.cpp +++ b/examples/example_inplace_polymorphic.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + namespace dtl = dice::template_library; struct animal { diff --git a/examples/example_integral_sequence.cpp b/examples/example_integral_sequence.cpp index 9c996aa..8760f8b 100644 --- a/examples/example_integral_sequence.cpp +++ b/examples/example_integral_sequence.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +import dice.template_library; + using namespace dice::template_library; // Example template that takes an integral value diff --git a/examples/example_limit_allocator.cpp b/examples/example_limit_allocator.cpp index 1a22112..aeff56e 100644 --- a/examples/example_limit_allocator.cpp +++ b/examples/example_limit_allocator.cpp @@ -1,8 +1,8 @@ -#include - #include #include +#include +import dice.template_library; int main() { std::vector> vec{dice::template_library::limit_allocator{3 * sizeof(int)}}; diff --git a/examples/example_mutex.cpp b/examples/example_mutex.cpp index 6b94307..e891f6e 100644 --- a/examples/example_mutex.cpp +++ b/examples/example_mutex.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + int main() { dice::template_library::mutex mut{0}; diff --git a/examples/example_next_to_range.cpp b/examples/example_next_to_range.cpp index b1c6e92..aff5c03 100644 --- a/examples/example_next_to_range.cpp +++ b/examples/example_next_to_range.cpp @@ -1,11 +1,11 @@ -#include - #include #include #include #include #include +import dice.template_library; + namespace dtl = dice::template_library; struct iota_iter_impl { diff --git a/examples/example_opt_minmax.cpp b/examples/example_opt_minmax.cpp index c7203ac..a7cc5c8 100644 --- a/examples/example_opt_minmax.cpp +++ b/examples/example_opt_minmax.cpp @@ -1,10 +1,10 @@ -#include - #include #include #include #include +import dice.template_library; + int main() { using namespace dice::template_library; diff --git a/examples/example_pointer_tag_pair.cpp b/examples/example_pointer_tag_pair.cpp index 4d70c62..29e3a31 100644 --- a/examples/example_pointer_tag_pair.cpp +++ b/examples/example_pointer_tag_pair.cpp @@ -1,6 +1,7 @@ #include +#include -#include +import dice.template_library; namespace dtl = dice::template_library; diff --git a/examples/example_pool_allocator.cpp b/examples/example_pool_allocator.cpp index cb5c87e..cac8157 100644 --- a/examples/example_pool_allocator.cpp +++ b/examples/example_pool_allocator.cpp @@ -1,10 +1,10 @@ -#include - #include #include #include #include +import dice.template_library; + struct list { uint64_t elem; list *next; diff --git a/examples/example_ranges.cpp b/examples/example_ranges.cpp index 722c4fc..cd19ab8 100644 --- a/examples/example_ranges.cpp +++ b/examples/example_ranges.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +import dice.template_library; + namespace dtl = dice::template_library; int main() { diff --git a/examples/example_shared_mutex.cpp b/examples/example_shared_mutex.cpp index a48c132..a28b55c 100644 --- a/examples/example_shared_mutex.cpp +++ b/examples/example_shared_mutex.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + int main() { dice::template_library::shared_mutex mut{0}; diff --git a/examples/example_static_string.cpp b/examples/example_static_string.cpp index acd6306..f50af82 100644 --- a/examples/example_static_string.cpp +++ b/examples/example_static_string.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +import dice.template_library; + int main() { assert(sizeof(dice::template_library::static_string) < sizeof(std::string)); diff --git a/examples/example_stdint.cpp b/examples/example_stdint.cpp index 43518d0..6cb3008 100644 --- a/examples/example_stdint.cpp +++ b/examples/example_stdint.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +import dice.template_library.literals; + int main() { using namespace dice::template_library::literals; diff --git a/examples/example_type_list.cpp b/examples/example_type_list.cpp index a7ebe1e..30b22d6 100644 --- a/examples/example_type_list.cpp +++ b/examples/example_type_list.cpp @@ -1,11 +1,11 @@ -#include - #include #include #include #include #include +import dice.template_library; + namespace tl = dice::template_library::type_list; int main() { diff --git a/examples/example_variant2.cpp b/examples/example_variant2.cpp index 1666b41..0d41977 100644 --- a/examples/example_variant2.cpp +++ b/examples/example_variant2.cpp @@ -2,8 +2,7 @@ #include #include -#include -#include +import dice.template_library; namespace dtl = dice::template_library; using namespace std::literals; diff --git a/examples/examples_fmt_join.cpp b/examples/examples_fmt_join.cpp index 51ad15c..1ba5ff5 100644 --- a/examples/examples_fmt_join.cpp +++ b/examples/examples_fmt_join.cpp @@ -4,7 +4,7 @@ #include #include -#include +import dice.template_library; namespace dtl = dice::template_library; using namespace std::literals; diff --git a/examples/examples_for.cpp b/examples/examples_for.cpp index 15fb541..e4888ea 100644 --- a/examples/examples_for.cpp +++ b/examples/examples_for.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + using namespace dice::template_library; // Types for constexpr for_values must be constexpr constructible. diff --git a/examples/examples_functional.cpp b/examples/examples_functional.cpp index 303048d..0ab282a 100644 --- a/examples/examples_functional.cpp +++ b/examples/examples_functional.cpp @@ -1,9 +1,10 @@ -#include #include #include #include #include +import dice.template_library; + int func(int x, int y) { return x + y; } diff --git a/examples/examples_integral_template_tuple.cpp b/examples/examples_integral_template_tuple.cpp index b97ba7b..91765ce 100644 --- a/examples/examples_integral_template_tuple.cpp +++ b/examples/examples_integral_template_tuple.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + using namespace dice::template_library; template diff --git a/examples/examples_integral_template_variant.cpp b/examples/examples_integral_template_variant.cpp index b4aefab..d33699f 100644 --- a/examples/examples_integral_template_variant.cpp +++ b/examples/examples_integral_template_variant.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + using namespace dice::template_library; template diff --git a/examples/examples_lazy_conditional.cpp b/examples/examples_lazy_conditional.cpp index 52eb9ef..f6507c6 100644 --- a/examples/examples_lazy_conditional.cpp +++ b/examples/examples_lazy_conditional.cpp @@ -1,8 +1,8 @@ -#include - #include #include +import dice.template_library; + namespace dice::template_library { template diff --git a/examples/examples_overloaded.cpp b/examples/examples_overloaded.cpp index 7c42461..31077ec 100644 --- a/examples/examples_overloaded.cpp +++ b/examples/examples_overloaded.cpp @@ -1,10 +1,9 @@ -#include -#include - #include #include #include +import dice.template_library; + namespace dtl = dice::template_library; diff --git a/examples/examples_polymorphic_allocator.cpp b/examples/examples_polymorphic_allocator.cpp index e5619de..05b8668 100644 --- a/examples/examples_polymorphic_allocator.cpp +++ b/examples/examples_polymorphic_allocator.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -8,6 +6,8 @@ #include #include +import dice.template_library; + template using shm_allocator_type = boost::interprocess::allocator; diff --git a/examples/examples_switch_cases.cpp b/examples/examples_switch_cases.cpp index 57cc7cb..a019e5a 100644 --- a/examples/examples_switch_cases.cpp +++ b/examples/examples_switch_cases.cpp @@ -1,7 +1,7 @@ -#include - #include +import dice.template_library; + using namespace dice::template_library; template diff --git a/examples/examples_tuple_algorithm.cpp b/examples/examples_tuple_algorithm.cpp index f2c0ed6..4f68a6b 100644 --- a/examples/examples_tuple_algorithm.cpp +++ b/examples/examples_tuple_algorithm.cpp @@ -1,10 +1,10 @@ -#include - #include #include #include #include +import dice.template_library; + void tuple_fold() { std::tuple tup{5, 1.2, 1.3F, 1L}; diff --git a/include/dice/template-library/defer.hpp b/include/dice/template-library/defer.hpp index e7a974a..16d7ec6 100644 --- a/include/dice/template-library/defer.hpp +++ b/include/dice/template-library/defer.hpp @@ -165,4 +165,35 @@ namespace dice::template_library { #define DICE_DEFER_TO_SUCCESS \ auto DICE_TEMPLATE_LIBRARY_DETAIL_SCOPEGUARD_VAR = ::dice::template_library::defer_detail::ScopeGuardOnSuccess{} + [&]() +/** + * Move a value if it is either a non-const rvalue-reference or just a value (without reference qualifiers). + * + * @param expr expression to potentially move + * + * @example + * @code + * int value; + * int &ref; + * int const &cref; + * int &&rref; + * int const &&crref; + * + * DICE_MOVE_IF_VALUE(value) // moves + * DICE_MOVE_IF_VALUE(rref) // moves + * + * DICE_MOVE_IF_VALUE(ref) // does not move + * DICE_MOVE_IF_VALUE(cref) // does not move + * DICE_MOVE_IF_VALUE(crref) // does not move + * @endcode + */ +#define DICE_MOVE_IF_VALUE(expr) \ + [&] || std::is_const_v>>() \ + -> std::conditional_t<_dice_detail_no_move, decltype(expr), std::add_rvalue_reference_t>> { \ + if constexpr (_dice_detail_no_move) { \ + return expr; \ + } else { \ + return std::move(expr); \ + } \ + }() + #endif // DICE_TEMPLATE_LIBRARY_DEFER_HPP diff --git a/include/dice/template-library/ranges.hpp b/include/dice/template-library/ranges.hpp index 1c94625..a4de63f 100644 --- a/include/dice/template-library/ranges.hpp +++ b/include/dice/template-library/ranges.hpp @@ -1,13 +1,6 @@ -#ifndef DICE_TEMPLATELIBRARY_HPP -#define DICE_TEMPLATELIBRARY_HPP +#ifndef DICE_TEMPLATE_LIBRARY_RANGES_H +#define DICE_TEMPLATE_LIBRARY_RANGES_H -#include - -#include -#include -#include -#include -#include // predicate based terminal algorithm #define DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(algo_name, impl_function, default_func, ...) \ @@ -49,648 +42,4 @@ \ __VA_ARGS__ inline constexpr ranges_algo_detail::algo_name##_fn algo_name; -namespace dice::template_library { - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_of, std::ranges::all_of, std::ranges::equal_to); - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(any_of, std::ranges::any_of, std::ranges::equal_to); - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(none_of, std::ranges::none_of, std::ranges::equal_to); -}// namespace dice::template_library - -// empty / non_empty terminal algorithm -namespace dice::template_library { - namespace ranges_algo_detail { - struct empty_fn { - template S> - constexpr bool operator()(I first, S last) const { - std::ranges::subrange range{std::move(first), std::move(last)}; - static_assert(requires { std::ranges::empty(range); }, "std::ranges::empty requires a forward range as it might otherwise be expensive to materialize the first element."); - return std::ranges::empty(range); - } - - template - constexpr bool operator()(R &&range) const { - static_assert(requires { std::ranges::empty(range); }, "std::ranges::empty requires a forward range as it might otherwise be expensive to materialize the first element."); - return std::ranges::empty(std::forward(range)); - } - - template - friend constexpr bool operator|(R &&range, empty_fn const &self) { - return self(std::forward(range)); - } - }; - - struct non_empty_fn { - template S> - constexpr bool operator()(I first, S last) const { - return !empty_fn{}(std::move(first), std::move(last)); - } - - template - constexpr bool operator()(R &&range) const { - return !empty_fn{}(std::forward(range)); - } - - template - friend constexpr bool operator|(R &&range, non_empty_fn const &self) { - return self(std::forward(range)); - } - }; - }// namespace ranges_algo_detail - - /** - * @brief Checks if a range is empty. - * - * This is a pipeable, terminal algorithm. It uses `std::ranges::empty` if available, - * otherwise it falls back to comparing `cbegin()` and `cend()`. - * - * @return A closure that returns true if the range is empty otherwise false. - */ - inline constexpr ranges_algo_detail::empty_fn empty{}; - - /** - * @brief Checks if a range is not empty. - * - * This is a pipeable, terminal algorithm and the logical negation of `dtl::empty`. - * - * @return A closure that returns true if the range has at least one element otherwise false. - */ - inline constexpr ranges_algo_detail::non_empty_fn non_empty{}; - -}// namespace dice::template_library - -// remove_element adaptor -namespace dice::template_library { - namespace ranges_algo_detail { - template - constexpr std::ranges::view auto remove_element_impl(R &&range, T remove_value, Pred pred = {}) { - return std::forward(range) - | std::views::filter([remove_value = std::move(remove_value), pred = std::move(pred)](auto const &element) { - return !std::invoke(pred, element, remove_value); - }); - } - - template - struct remove_element_pipeline { - private: - T value_; - Pred pred_; - - public: - template - constexpr remove_element_pipeline(V &&value, P &&pred) - : value_{std::forward(value)}, pred_{std::forward

(pred)} { - } - - template - friend constexpr std::ranges::view auto operator|(R &&range, remove_element_pipeline const &self) { - return remove_element_impl(std::forward(range), self.value_, self.pred_); - } - }; - - struct remove_element_fn { - template - constexpr auto operator()(T remove_value, Pred pred = {}) const { - return remove_element_pipeline{std::move(remove_value), std::move(pred)}; - } - }; - }// namespace ranges_algo_detail - - /** - * Creates a lazy, pipeable view of a range that excludes elements matching a given value. This adaptor does not modify the source range. - * - * @param value The value to filter out of the source range. - * @param pred Optional binary predicate for comparison. Defaults to `std::ranges::equal_to`. - * @return A range adaptor closure. - * - * @note This view is deprecated because it is not possible to make it callable as a regular function and pipelineable - * at the same time due to overload resolution issues with ranges of ranges. - * Additionally, this is just a `std::views::filter([remove_value](auto const &x) { return x != remove_value });`, use that instead. - */ - [[deprecated("Use std::views::filter")]] inline constexpr ranges_algo_detail::remove_element_fn remove_element; - -}// namespace dice::template_library - -// all_equal adaptor -namespace dice::template_library { - namespace ranges_algo_detail { - template S, typename Pred = std::ranges::equal_to> - requires (std::copyable>) - bool all_equal_impl(I first, S last, Pred pred) { - if (first == last) { - return true; - } - - auto const first_element = *first; - ++first; - - // Check if all subsequent elements in the range match the first one. - return std::ranges::subrange(first, last) - | dice::template_library::all_of([&](auto const ¤t_element) { - return std::invoke(pred, current_element, first_element); - }); - } - }// namespace ranges_algo_detail - - /** - * @brief Checks if all elements in a range are equal to each other. - * - * This is a pipeable, terminal algorithm that returns a boolean. Elements must be copyable for this to work. - * - * @param pred Optional binary predicate for comparison. Defaults to `std::ranges::equal_to`. - * @return true if all elements in the range are equal, otherwise false. - */ - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_equal, ranges_algo_detail::all_equal_impl, std::ranges::equal_to); -}// namespace dice::template_library - -// unique adaptor -namespace dice::template_library { - namespace ranges_algo_detail { - - template - concept unordered_set_elem = std::equality_comparable && requires (T const &elem) { - { std::hash{}(elem) } -> std::convertible_to; - }; - - template - concept set_elem = std::strict_weak_order, T, T>; - - template - requires std::ranges::view - struct unique_view : std::ranges::view_interface> { - struct iterator; - using sentinel = std::default_sentinel_t; - - private: - R base_; - - public: - explicit constexpr unique_view(R const &base) : base_{base} {} - explicit constexpr unique_view(R &&base) : base_{std::move(base)} {} - - constexpr iterator begin() { - return iterator{*this}; - } - - constexpr sentinel end() const noexcept { - return std::default_sentinel; - } - }; - - template - requires std::ranges::view - struct unique_view::iterator { - using iterator_category = std::input_iterator_tag; - using value_type = std::ranges::range_value_t; - using difference_type = std::ranges::range_difference_t; - - private: - using set_value_type = std::remove_cvref_t>; - - static_assert(std::copy_constructible, - "The value type for unique must be copy-constructible."); - - static_assert(set_elem || unordered_set_elem, - "The value type must be either hashable and equality comparable, or support less than."); - - using set_type = std::conditional_t< - unordered_set_elem,// prioritize unordered_set - std::unordered_set, - std::set>; - - set_type seen_; - std::ranges::iterator_t current_; - [[no_unique_address]] std::ranges::sentinel_t end_; - - void find_next_unique() { - while (current_ != end_) { - if (seen_.insert(*current_).second) { - break; - } - ++current_; - } - } - - public: - explicit constexpr iterator(unique_view &parent) - : seen_{}, - current_{std::ranges::begin(parent.base_)}, - end_{std::ranges::end(parent.base_)} { - find_next_unique(); - } - - constexpr decltype(auto) operator*() const { - return *current_; - } - - constexpr iterator &operator++() { - ++current_; - find_next_unique(); - return *this; - } - - constexpr void operator++(int) { - ++*this; - } - - friend constexpr bool operator==(iterator const &self, std::default_sentinel_t) { - return self.current_ == self.end_; - } - - friend constexpr bool operator==(std::default_sentinel_t sent, iterator const &self) { - return self == sent; - } - }; - - struct unique_fn { - template - constexpr auto operator()(R &&r) const { - return unique_view(std::views::all(std::forward(r))); - } - - template - friend constexpr auto operator|(R &&r, unique_fn const &self) { - return self(std::forward(r)); - } - }; - }// namespace ranges_algo_detail - - /** - * @brief A range adaptor that produces a view containing the first occurrence of each element from an underlying range. - * - * This adaptor is lazy and preserves the relative order of the unique elements. It automatically uses a hash set - * for tracking if the element type is hashable, otherwise it falls back to a sorted set. - * - * @return A lazy view containing the unique elements. - */ - [[deprecated("This view is inefficient and will be removed. Manually construct a set, or use a combination of chunk_by and transform " - "on sorted ranges.")]] inline constexpr ranges_algo_detail::unique_fn unique; - -}// namespace dice::template_library - - -namespace dice::template_library { - - template - concept step_for = std::is_default_constructible_v && requires (T start, T const stop, S step) { - { start <= stop } -> std::convertible_to; - { start >= stop } -> std::convertible_to; - - start += step; - }; - - namespace ranges_algo_detail { - /** - * range generator (python-like iota with step) implemented as a rust-like next() iterator - * - * @tparam T range return type - * @tparam S step type for range (can also be a signed type even though T is unsigned) - */ - template S> - struct range_iterator { - using value_type = T; - - private: - T current_; - T stop_; - S step_; - - public: - range_iterator() noexcept - requires (std::is_default_constructible_v && std::is_constructible_v) - : current_{}, - stop_{}, - step_{1} { - } - - explicit constexpr range_iterator(T start, T stop, S step) - : current_{start}, stop_{stop}, step_{step} { - if (step == S{}) [[unlikely]] { - throw std::invalid_argument{"range: step must not be the zero element/the additive identity"}; - } - } - - [[nodiscard]] constexpr std::optional next() noexcept { - if (step_ > S{}) { - if (current_ >= stop_) { - return std::nullopt; - } - } else { - if (current_ <= stop_) { - return std::nullopt; - } - } - - return std::exchange(current_, current_ + step_); - } - - [[nodiscard]] constexpr size_t remaining() const noexcept - requires (std::integral && std::integral) - { - if (current_ <= stop_) { - // forward - if (step_ < S{}) { - // wrong direction - return 0; - } - - return static_cast((stop_ - current_ + step_ - 1) / step_); - } else { - // backward - if (step_ > S{}) { - // wrong direction - return 0; - } - - return static_cast((current_ - stop_ + -step_ - 1) / -step_); - } - } - - [[nodiscard]] constexpr std::optional nth(size_t off) noexcept - requires (std::integral && std::integral) - { - auto const rem = remaining(); - if (off >= rem) { - current_ = stop_; - return std::nullopt; - } - - current_ += static_cast(off) * step_; - return next(); - } - - [[nodiscard]] constexpr std::optional next_back() noexcept - requires (std::integral && std::integral) - { - if (step_ > S{}) { - if (current_ >= stop_) { - return std::nullopt; - } - stop_ -= step_; - return stop_; - } else { - if (current_ <= stop_) { - return std::nullopt; - } - stop_ -= step_; - return stop_; - } - } - - [[nodiscard]] constexpr std::optional nth_back(size_t off) noexcept - requires (std::integral && std::integral) - { - auto const rem = remaining(); - if (off >= rem) { - stop_ = current_; - return std::nullopt; - } - - stop_ -= static_cast(off) * step_; - return next_back(); - } - }; - }// namespace ranges_algo_detail - - template - using range_view = next_to_view>; - - /** - * @brief A lazy view that generates a sequence of numbers, similar to Python's range(). - * - * This view can be used with one, two, or three arguments: - * - `range(stop)`: Generates [0,stop). - * - `range(start, stop)`: Generates [start,stop). - * - `range(start, stop, step)`: Generates numbers from start, incrementing by step, until stop is met or passed. - */ - template - [[nodiscard]] constexpr range_view range(T start, T stop, S step) { - return range_view{start, stop, step}; - } - - template - requires (std::is_constructible_v && step_for) - [[nodiscard]] constexpr range_view range(T start, T stop) { - return range_view{start, stop, T(1)}; - } - - template - requires (std::is_default_constructible_v && std::is_constructible_v) - [[nodiscard]] constexpr range_view range(T stop) { - return range_view{T{}, stop, T(1)}; - } - -}// namespace dice::template_library - -// all_distinct terminal algorithm -namespace dice::template_library { - namespace ranges_algo_detail { - template S, typename Pred = std::ranges::equal_to> - [[nodiscard]] constexpr bool all_distinct_impl(I first, S last, Pred pred) { - using value_type = std::remove_cvref_t>; - static_assert(unordered_set_elem || (set_elem && std::is_same_v), - "The elements of the consumed range are neither compatible with std::unordered_set nor with std::set."); - - if (first == last) { - return true; - } - - auto seen = [&] { - if constexpr (unordered_set_elem) { - return std::unordered_set, Pred>{1, {}, std::move(pred)}; - } else { - return std::set{}; - } - }(); - - for (; first != last; ++first) { - if (!seen.insert(*first).second) { - return false; - } - } - return true; - } - - template S, typename Pred = std::ranges::equal_to> - [[nodiscard]] constexpr bool all_distinct_sorted_impl(I first, S last, Pred pred) { - return std::ranges::adjacent_find(first, last, std::move(pred)) == last; - } - } // namespace ranges_algo_detail - - /** - * @brief Checks if all elements in a range are distinct from one another. - * - * This is a pipeable, terminal algorithm that returns a boolean. - * - When called without arguments, it uses a hash set if the type is hashable, otherwise it - * falls back to a sorted set if the type is comparable. - * - When called with a custom equality predicate, it requires the type to be hashable. - * - * @param pred Optional binary predicate for equality comparison. Defaults to `std::ranges::equal_to`. - * @return true if all elements are distinct, otherwise false. - */ - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_distinct, - ranges_algo_detail::all_distinct_impl, - std::ranges::equal_to, - [[deprecated("This algorithm is inefficient and will be removed. Manually construct a set, or use " - "std::ranges::adjacent_find in sorted ranges to check for distinctness.")]]); -} // namespace dice::template_library - -// is_sorted_unique terminal algorithm -namespace dice::template_library { - namespace ranges_algo_detail { - template S, typename Cmp, typename Proj> - requires (std::indirect_strict_weak_order>) - constexpr bool is_sorted_unique_impl(I first, S last, Cmp cmp, Proj proj) { - if (first == last) { - return true; - } - - auto it = first; - while (++it != last) { - // We require that 'prev' is strictly less than 'curr'. - // cmp(a, b) ~ a < b - // <-> !cmp(a, b) ~ a >= b - if (!std::invoke(cmp, std::invoke(proj, *first), std::invoke(proj, *it))) { - return false; - } - first = it; - } - return true; - } - - template - struct is_sorted_unique_pipeline { - private: - [[no_unique_address]] Cmp cmp_; - [[no_unique_address]] Proj proj_; - - public: - is_sorted_unique_pipeline(Cmp cmp, Proj proj) - : cmp_{std::move(cmp)}, proj_{std::move(proj)} { - } - - template - [[nodiscard]] friend constexpr bool operator|(R &&range, is_sorted_unique_pipeline const &self) { - return is_sorted_unique_impl(std::ranges::begin(range), std::ranges::end(range), self.cmp_, self.proj_); - } - }; - - struct is_sorted_unique_fn { - /** - * Return true iff the given range is sorted and there are no duplicates. - * - * @param range range to check - * @param cmp comparator - * @param proj projection - */ - template - [[nodiscard]] constexpr bool operator()(R &&range, Cmp cmp = {}, Proj proj = {}) const { - return is_sorted_unique_impl(std::ranges::begin(range), std::ranges::end(range), std::move(cmp), std::move(proj)); - } - - /** - * Return true iff the given range is sorted and there are no duplicates. - * - * @param first iterator to start of range - * @param last sentinel for range - * @param cmp comparator - * @param proj projection - * @return - */ - template S, typename Cmp = std::ranges::less, typename Proj = std::identity> - [[nodiscard]] constexpr bool operator()(I first, S last, Cmp cmp = {}, Proj proj = {}) const { - return is_sorted_unique_impl(std::move(first), std::move(last), std::move(cmp), std::move(proj)); - } - - /** - * Pipeline overload for is_strictly_sorted - */ - template - requires (!std::ranges::input_range && !std::input_iterator) - [[nodiscard]] constexpr auto operator()(Cmp cmp = {}, Proj proj = {}) const { - return is_sorted_unique_pipeline{std::move(cmp), std::move(proj)}; - } - }; - } // namespace ranges_algo_detail - - /** - * Return true iff the given range is sorted and there are no duplicates. - * - * @param range or first+last range to check - * @param cmp comparator - * @param proj projection - */ - inline constexpr ranges_algo_detail::is_sorted_unique_fn is_sorted_unique; - - namespace ranges_algo_detail { - struct lexicographical_compare_three_way_fn { - /** - * Lexicographically compares two ranges range1 and range2 - * - * @param range1 first range - * @param range2 second range - * @param cmp three-way comparator - * @param proj1 projection for first range - * @param proj2 projection for second range - * @return lexicographical three-way compare result of the two ranges - */ - template - [[nodiscard]] constexpr auto operator()(R1 &&range1, R2 &&range2, Cmp cmp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { - return lexicographical_compare_three_way_fn{}(std::ranges::begin(range1), std::ranges::end(range1), std::ranges::begin(range2), std::ranges::end(range2), cmp, proj1, proj2); - } - - /** - * Lexicographically compares two ranges [first1, last1) and [first2, last2) using three-way comparison. - * - * @param first1 iterator to start of first range - * @param last1 sentinel for first range - * @param first2 iterator to start of second range - * @param last2 sentinel for second range - * @param cmp three-way comparator - * @param proj1 projection for first range - * @param proj2 projection for second range - * @return lexicographical three-way compare result of the two ranges - */ - template S1, std::input_iterator I2, std::sentinel_for S2, typename Proj1 = std::identity, typename Proj2 = std::identity, typename Cmp = std::compare_three_way> - [[nodiscard]] constexpr auto operator()(I1 first1, S1 last1, I2 first2, S2 last2, Cmp cmp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { - using proj1_res = std::indirect_result_t; - using proj2_res = std::indirect_result_t; - using cmp_cat = std::invoke_result_t; - - while (first1 != last1 && first2 != last2) { - auto const res = std::invoke(cmp, std::invoke(proj1, *first1), std::invoke(proj2, *first2)); - if (res != 0) { - return res; - } - - ++first1; - ++first2; - } - - bool const exhaust1 = first1 == last1; - bool const exhaust2 = first2 == last2; - - if (exhaust1 && exhaust2) { - return cmp_cat{std::strong_ordering::equal}; - } - if (exhaust1) { - return cmp_cat{std::strong_ordering::less}; - } - return cmp_cat{std::strong_ordering::greater}; - } - }; - } // namespace ranges_algo_detail - - /** - * Lexicographically compares two ranges range1/[first1, last1) and range2/[first2, last2) using three-way comparison. - * - * @param range1 or first1+last1 first range - * @param range2 or first2+last2 second range - * @param cmp three-way comparator - * @param proj1 projection for first range - * @param proj2 projection for second range - * @return lexicographical three-way compare result of the two ranges - */ - inline constexpr ranges_algo_detail::lexicographical_compare_three_way_fn lexicographical_compare_three_way; - -}// namespace dice::template_library - -#endif// DICE_TEMPLATELIBRARY_HPP +#endif //DICE_TEMPLATE_LIBRARY_RANGES_H diff --git a/include/dice/template-library/channel.hpp b/src/dice/template-library/channel.cppm similarity index 98% rename from include/dice/template-library/channel.hpp rename to src/dice/template-library/channel.cppm index d5b685e..65c5dfc 100644 --- a/include/dice/template-library/channel.hpp +++ b/src/dice/template-library/channel.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_CHANNEL_HPP -#define DICE_TEMPLATELIBRARY_CHANNEL_HPP - +module; #include #include #include @@ -9,7 +7,9 @@ #include #include -namespace dice::template_library { +export module dice.template_library:channel; + +export namespace dice::template_library { /** * A multi producer, multi consumer channel/queue @@ -307,5 +307,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_CHANNEL_HPP diff --git a/src/dice/template-library/dtl.cppm b/src/dice/template-library/dtl.cppm new file mode 100644 index 0000000..aa6b9ee --- /dev/null +++ b/src/dice/template-library/dtl.cppm @@ -0,0 +1,38 @@ +module; +#if __has_include() +#define HAS_BOOST_INTERPROCESS_OFFSET +#endif + +export module dice.template_library; + +export import :version; +export import :channel; +export import :flex_array; +export import :fmt_join; +export import :for_loop; +export import :format_to_ostream; +export import :functional; +export import :type_traits; +export import :inplace_poly; +export import :type_list; +export import :integral_template_tuple; +export import :standard_layout_tuple; +export import :tuple_algo; +export import :lazy_conditional; +export import :integral_template_variant; +export import :limit_allocator; +export import :mutex; +export import :next_to_range; +export import :ranges; +export import :opt_minmax; +export import :overloaded; +export import :pointer_tag_pair; +export import :variant2; +export import :polymorphic_allocator; +#ifdef HAS_BOOST_INTERPROCESS_OFFSET +export import :pool_allocator; +#endif +export import :shared_mutex; +export import :static_string; +export import :switch_cases; +export import :integral_sequence; diff --git a/include/dice/template-library/flex_array.hpp b/src/dice/template-library/flex_array.cppm similarity index 98% rename from include/dice/template-library/flex_array.hpp rename to src/dice/template-library/flex_array.cppm index e7ebfcd..8359c29 100644 --- a/include/dice/template-library/flex_array.hpp +++ b/src/dice/template-library/flex_array.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_FLEXARRAY_HPP -#define DICE_TEMPLATELIBRARY_FLEXARRAY_HPP - +module; #include #include #include @@ -13,7 +11,9 @@ #include #endif // __has_include -namespace dice::template_library { +export module dice.template_library:flex_array; + +export namespace dice::template_library { using std::dynamic_extent; /** @@ -420,5 +420,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_FLEXARRAY_HPP diff --git a/include/dice/template-library/fmt_join.hpp b/src/dice/template-library/fmt_join.cppm similarity index 91% rename from include/dice/template-library/fmt_join.hpp rename to src/dice/template-library/fmt_join.cppm index 6d79999..54a1c93 100644 --- a/include/dice/template-library/fmt_join.hpp +++ b/src/dice/template-library/fmt_join.cppm @@ -1,11 +1,11 @@ -#ifndef DICE_TEMPLATE_LIBRARY_FMT_JOIN_HPP -#define DICE_TEMPLATE_LIBRARY_FMT_JOIN_HPP - +module; #include #include #include #include +export module dice.template_library:fmt_join; + namespace dice::template_library { namespace fmt_join_algo_detail { @@ -27,12 +27,12 @@ namespace dice::template_library { * @param separator A string-like object (e.g., ", ") to place between elements. * @return A helper object for use by `std::format`. */ - template + export template constexpr auto fmt_join(R &&range, Sep &&separator) { return fmt_join_algo_detail::joiner{std::views::all(std::forward(range)), std::forward(separator)}; } - template + export template constexpr auto fmt_join(std::initializer_list range, Sep &&separator) { return fmt_join_algo_detail::joiner{std::views::all(std::vector(range)), std::forward(separator)}; } @@ -40,7 +40,7 @@ namespace dice::template_library { }// namespace dice::template_library // actual implementation of fmt_join -namespace std { +export namespace std { template struct formatter, CharT> { private: @@ -84,5 +84,3 @@ namespace std { }; }// namespace std - -#endif// DICE_TEMPLATE_LIBRARY_FMT_JOIN_HPP diff --git a/include/dice/template-library/for.hpp b/src/dice/template-library/for.cppm similarity index 92% rename from include/dice/template-library/for.hpp rename to src/dice/template-library/for.cppm index 4abfdd8..e0f0129 100644 --- a/include/dice/template-library/for.hpp +++ b/src/dice/template-library/for.cppm @@ -1,11 +1,11 @@ -#ifndef DICE_TEMPLATE_LIBRARY_FOR_HPP -#define DICE_TEMPLATE_LIBRARY_FOR_HPP - +module; #include #include #include -namespace dice::template_library { +export module dice.template_library:for_loop; + +export namespace dice::template_library { /** * Call a templated lambda with each of the provided types Ts... * @tparam Ts The types with which the lambda should be called. @@ -54,4 +54,3 @@ namespace dice::template_library { } } }// namespace dice::template_library -#endif//DICE_TEMPLATE_LIBRARY_FOR_HPP diff --git a/include/dice/template-library/format_to_ostream.hpp b/src/dice/template-library/format_to_ostream.cppm similarity index 82% rename from include/dice/template-library/format_to_ostream.hpp rename to src/dice/template-library/format_to_ostream.cppm index 01e6e98..d7d0777 100644 --- a/include/dice/template-library/format_to_ostream.hpp +++ b/src/dice/template-library/format_to_ostream.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_FORMAT_TO_OSTREAM -#define DICE_TEMPLATELIBRARY_FORMAT_TO_OSTREAM - +module; /*! * Note: This file does not use concepts/requires anywhere because their evaluation * causes an infinite loop (compiler error: "evaluation of constraint depends on itself"). @@ -14,6 +12,8 @@ #include #include +export module dice.template_library:format_to_ostream; + namespace dice::template_library { /** @@ -45,10 +45,8 @@ namespace dice::template_library { * @param value value to stream via std::formatter implementation * @return stream */ -template, typename = std::enable_if_t && !dice::template_library::is_ostreamable_v>> +export template, typename = std::enable_if_t && !dice::template_library::is_ostreamable_v>> std::basic_ostream &operator<<(std::basic_ostream &stream, T const &value) { std::format_to(std::ostreambuf_iterator{stream}, "{}", value); return stream; } - -#endif // DICE_TEMPLATELIBRARY_FORMAT_TO_OSTREAM diff --git a/include/dice/template-library/functional.hpp b/src/dice/template-library/functional.cppm similarity index 87% rename from include/dice/template-library/functional.hpp rename to src/dice/template-library/functional.cppm index 1d99339..3af945f 100644 --- a/include/dice/template-library/functional.hpp +++ b/src/dice/template-library/functional.cppm @@ -1,12 +1,13 @@ -#ifndef DICE_TEMPLATELIBRARY_FUNCTIONAL_HPP -#define DICE_TEMPLATELIBRARY_FUNCTIONAL_HPP - -#include +module; #include #include #include +export module dice.template_library:functional; + +export import :type_traits; + namespace dice::template_library { namespace detail_bind_front { @@ -31,7 +32,7 @@ namespace dice::template_library { * * @note this implementation mainly exists because the version with constexpr function is only available since C++26 */ - template + export template [[nodiscard]] constexpr auto bind_front(BindArgs &&...bind_args) { using func_t = decltype(func); @@ -42,5 +43,3 @@ namespace dice::template_library { } }// namespace dice::template_library - -#endif// DICE_TEMPLATELIBRARY_FUNCTIONAL_HPP diff --git a/include/dice/template-library/inplace_polymorphic.hpp b/src/dice/template-library/inplace_polymorphic.cppm similarity index 97% rename from include/dice/template-library/inplace_polymorphic.hpp rename to src/dice/template-library/inplace_polymorphic.cppm index d354c6c..b5b6cb6 100644 --- a/include/dice/template-library/inplace_polymorphic.hpp +++ b/src/dice/template-library/inplace_polymorphic.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_INPLACEPOLYMORPHIC_HPP -#define DICE_TEMPLATELIBRARY_INPLACEPOLYMORPHIC_HPP - +module; #include #include #include @@ -10,6 +8,8 @@ #include #include +export module dice.template_library:inplace_poly; + #define DICE_TEMPLATELIBRARY_DETAIL_INPLACEPOLY_TRY(noexcept_spec, action_block) \ if constexpr (noexcept_spec) { \ action_block \ @@ -56,7 +56,7 @@ namespace dice::template_library { * @tparam Base base class for all Ts... * @tparam Ts derived classes of Base */ - template ...Ts> + export template ...Ts> struct inplace_polymorphic { static_assert(sizeof...(Ts) > 0, "A inplace_polymorphic with no Ts... has no valid values."); @@ -295,5 +295,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_INPLACEPOLYMORPHIC_HPP diff --git a/include/dice/template-library/integral_sequence.hpp b/src/dice/template-library/integral_sequence.cppm similarity index 58% rename from include/dice/template-library/integral_sequence.hpp rename to src/dice/template-library/integral_sequence.cppm index 6b8fda7..eb1dc3c 100644 --- a/include/dice/template-library/integral_sequence.hpp +++ b/src/dice/template-library/integral_sequence.cppm @@ -1,14 +1,34 @@ -#ifndef DICE_TEMPLATE_LIBRARY_INTEGRAL_SEQUENCE_HPP -#define DICE_TEMPLATE_LIBRARY_INTEGRAL_SEQUENCE_HPP - -#include - +module; #include #include #include #include +export module dice.template_library:integral_sequence; + +export import :type_list; + namespace dice::template_library { + namespace detail_integer_sequence { + template + constexpr auto make_integer_sequence() { + if constexpr (first == last) { + return std::integer_sequence{}; + } else if constexpr (first < last) { + // Ascending [first, last) + auto const impl = [](std::integer_sequence) { + return std::integer_sequence{}; + }; + return impl(std::make_integer_sequence{}); + } else { + // Descending (last, first] + auto const impl = [](std::integer_sequence) { + return std::integer_sequence{}; + }; + return impl(std::make_integer_sequence{}); + } + } + } /** * Generate an integer_sequence for a range @@ -22,35 +42,19 @@ namespace dice::template_library { * - first < last: ascending [first, last) * - first > last: descending (last, first] */ - template - using make_integer_sequence = decltype([] { - if constexpr (first == last) { - return std::integer_sequence{}; - } else if constexpr (first < last) { - // Ascending [first, last) - auto const impl = [](std::integer_sequence) { - return std::integer_sequence{}; - }; - return impl(std::make_integer_sequence{}); - } else { - // Descending (last, first] - auto const impl = [](std::integer_sequence) { - return std::integer_sequence{}; - }; - return impl(std::make_integer_sequence{}); - } - }()); + export template + using make_integer_sequence = decltype(detail_integer_sequence::make_integer_sequence()); /** * Generate a std::index_sequence, i.e., integer_sequence for a range */ - template + export template using make_index_sequence = make_integer_sequence; /** * Generate a type_list of std::integral_constant for each ix in the sequence */ - template + export template using make_integral_constant_list = type_list::integer_sequence_to_type_list_t>; @@ -59,6 +63,10 @@ namespace dice::template_library { * Provides a unified interface for generating integer_sequence, index_sequence, type_list, and more. */ namespace detail_integral_template_util { + template typename T> + constexpr auto make_type_list_fun = [](std::type_identity>) { + return std::type_identity>{}; + }; /** * Generate a type_list by applying a template to each index in the sequence * @@ -69,11 +77,7 @@ namespace dice::template_library { * Direction is automatic based on first vs last */ template typename T> - using make_type_list = type_list::transform_t< - make_integral_constant_list, - [](std::type_identity>) { - return std::type_identity>{}; - }>; + using make_type_list = type_list::transform_t, make_type_list_fun>; /** * Check if an index is valid for a given range @@ -110,5 +114,3 @@ namespace dice::template_library { } // namespace detail_integral_template_util }// namespace dice::template_library - -#endif//DICE_TEMPLATE_LIBRARY_INTEGRAL_SEQUENCE_HPP diff --git a/include/dice/template-library/integral_template_tuple.hpp b/src/dice/template-library/integral_template_tuple.cppm similarity index 89% rename from include/dice/template-library/integral_template_tuple.hpp rename to src/dice/template-library/integral_template_tuple.cppm index 07e40cd..f4c36aa 100644 --- a/include/dice/template-library/integral_template_tuple.hpp +++ b/src/dice/template-library/integral_template_tuple.cppm @@ -1,17 +1,17 @@ -#ifndef DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_TUPLE_V2_HPP -#define DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_TUPLE_V2_HPP - -#include -#include -#include -#include -#include - +module; #include #include #include #include +export module dice.template_library:integral_template_tuple; + +export import :type_list; +export import :type_traits; +export import :integral_sequence; +export import :standard_layout_tuple; +export import :tuple_algo; + namespace dice::template_library { namespace detail_itt { @@ -34,7 +34,7 @@ namespace dice::template_library { * @tparam last last ix (exclusive, not included in the tuple) * @tparam T the template that gets instantiated with T */ - template typename T> + export template typename T> struct integral_template_tuple : detail_itt::make_tuple { using index_type = decltype(first); @@ -126,5 +126,3 @@ namespace dice::template_library { }; }// namespace dice::template_library - -#endif//DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_TUPLE_V2_HPP diff --git a/include/dice/template-library/integral_template_variant.hpp b/src/dice/template-library/integral_template_variant.cppm similarity index 90% rename from include/dice/template-library/integral_template_variant.hpp rename to src/dice/template-library/integral_template_variant.cppm index fdbe8ee..5bfe3d1 100644 --- a/include/dice/template-library/integral_template_variant.hpp +++ b/src/dice/template-library/integral_template_variant.cppm @@ -1,16 +1,16 @@ -#ifndef DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_VARIANT_V2_HPP -#define DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_VARIANT_V2_HPP - -#include -#include -#include -#include - +module; #include #include #include #include +export module dice.template_library:integral_template_variant; + +export import :integral_sequence; +export import :type_list; +export import :type_traits; +export import :lazy_conditional; + namespace dice::template_library { namespace detail_itv { @@ -44,7 +44,7 @@ namespace dice::template_library { * @tparam last the last ix (exclusive, not included in the variant) * @tparam T the template that gets instantiated with T */ - template typename T> + export template typename T> struct integral_template_variant { using index_type = decltype(first); using underlying_type = detail_itv::make_variant; @@ -134,12 +134,10 @@ namespace dice::template_library { }// namespace dice::template_library -template typename T> +export template typename T> struct std::hash<::dice::template_library::integral_template_variant> { [[nodiscard]] size_t operator()(::dice::template_library::integral_template_variant const &variant) const noexcept { using underlying_type = typename ::dice::template_library::integral_template_variant::underlying_type; return std::hash{}(variant.to_underlying()); } }; - -#endif//DICE_TEMPLATE_LIBRARY_INTEGRAL_TEMPLATE_VARIANT_V2_HPP diff --git a/include/dice/template-library/lazy_conditional.hpp b/src/dice/template-library/lazy_conditional.cppm similarity index 96% rename from include/dice/template-library/lazy_conditional.hpp rename to src/dice/template-library/lazy_conditional.cppm index 6da706a..30ce6ef 100644 --- a/include/dice/template-library/lazy_conditional.hpp +++ b/src/dice/template-library/lazy_conditional.cppm @@ -1,10 +1,10 @@ -#ifndef DICE_TEMPLATE_LIBRARY_LAZY_CONDITIONAL_HPP -#define DICE_TEMPLATE_LIBRARY_LAZY_CONDITIONAL_HPP - +module; #include #include -namespace dice::template_library { +export module dice.template_library:lazy_conditional; + +export namespace dice::template_library { /** * Concept for type providers that have a ::type member (checks without instantiating). @@ -183,5 +183,3 @@ namespace dice::template_library { using lazy_switch_t = lazy_switch::type; }// namespace dice::template_library - -#endif// DICE_TEMPLATE_LIBRARY_LAZY_CONDITIONAL_HPP \ No newline at end of file diff --git a/include/dice/template-library/limit_allocator.hpp b/src/dice/template-library/limit_allocator.cppm similarity index 95% rename from include/dice/template-library/limit_allocator.hpp rename to src/dice/template-library/limit_allocator.cppm index e836280..97d87c9 100644 --- a/include/dice/template-library/limit_allocator.hpp +++ b/src/dice/template-library/limit_allocator.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_LIMITALLOCATOR_HPP -#define DICE_TEMPLATELIBRARY_LIMITALLOCATOR_HPP - +module; #include #include #include @@ -8,12 +6,14 @@ #include #include +export module dice.template_library:limit_allocator; + namespace dice::template_library { /** * The synchronization policy of a limit_allocator */ - enum struct limit_allocator_syncness : bool { + export enum struct limit_allocator_syncness : bool { sync, ///< thread-safe (synchronized) unsync, ///< not thread-safe (unsynchronized) }; @@ -66,7 +66,7 @@ namespace dice::template_library { * @tparam Allocator the underlying allocator * @tparam syncness determines the synchronization of the limit */ - template typename Allocator = std::allocator, limit_allocator_syncness syncness = limit_allocator_syncness::sync> + export template typename Allocator = std::allocator, limit_allocator_syncness syncness = limit_allocator_syncness::sync> struct limit_allocator { using control_block_type = detail_limit_allocator::limit_allocator_control_block; using value_type = T; @@ -172,5 +172,3 @@ namespace dice::template_library { bool operator!=(limit_allocator const &other) const noexcept = default; }; }// namespace dice::template_library - -#endif// DICE_TEMPLATELIBRARY_LIMITALLOCATOR_HPP \ No newline at end of file diff --git a/include/dice/template-library/mutex.hpp b/src/dice/template-library/mutex.cppm similarity index 95% rename from include/dice/template-library/mutex.hpp rename to src/dice/template-library/mutex.cppm index 39746f0..3109fea 100644 --- a/include/dice/template-library/mutex.hpp +++ b/src/dice/template-library/mutex.cppm @@ -1,14 +1,14 @@ -#ifndef DICE_TEMPLATELIBRARY_MUTEX_HPP -#define DICE_TEMPLATELIBRARY_MUTEX_HPP - +module; #include #include #include #include +export module dice.template_library:mutex; + namespace dice::template_library { - template + export template struct mutex; /** @@ -22,7 +22,7 @@ namespace dice::template_library { * @tparam T the value type protected by the mutex * @tparam Mutex the mutex type */ - template + export template struct mutex_guard { using value_type = T; using mutex_type = Mutex; @@ -130,5 +130,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_MUTEX_HPP diff --git a/include/dice/template-library/next_to_range.hpp b/src/dice/template-library/next_to_range.cppm similarity index 97% rename from include/dice/template-library/next_to_range.hpp rename to src/dice/template-library/next_to_range.cppm index 38ed862..d47c03a 100644 --- a/include/dice/template-library/next_to_range.hpp +++ b/src/dice/template-library/next_to_range.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_NEXTTORANGE_HPP -#define DICE_TEMPLATELIBRARY_NEXTTORANGE_HPP - +module; #include #include #include @@ -11,11 +9,13 @@ #include #include +export module dice.template_library:next_to_range; + namespace dice::template_library { /** * A rust-style forward iterator with next() that consumes elements from the front. */ - template + export template concept next_iterator = requires (I &iter) { typename I::value_type; { iter.next() } -> std::same_as>; @@ -24,7 +24,7 @@ namespace dice::template_library { /** * A rust-style backwards iterator with a next_back() function that consumes elements from the back. */ - template + export template concept next_back_iterator = requires (I &iter) { typename I::value_type; { iter.next_back() } -> std::same_as>; @@ -33,7 +33,7 @@ namespace dice::template_library { /** * A rust-style forward iterator with nth(off) that consumes elements from the front. */ - template + export template concept nth_iterator = requires (I &iter, size_t off) { typename I::value_type; { iter.nth(off) } -> std::same_as>; @@ -42,7 +42,7 @@ namespace dice::template_library { /** * A rust-style backwards iterator with nth_back(off) that consumes elements from the front. */ - template + export template concept nth_back_iterator = requires (I &iter, size_t off) { typename I::value_type; { iter.nth_back(off) } -> std::same_as>; @@ -51,7 +51,7 @@ namespace dice::template_library { /** * A rust-style iterator that knows how many elements it has left. */ - template + export template concept sized_next_iterator = requires (I const &iter) { { iter.remaining() } -> std::convertible_to; }; @@ -217,7 +217,7 @@ namespace dice::template_library { * // Enables operator+= (and operator+ **if Iter is copy-constructible**) * { iter.nth(size_t{off}) } -> std::optional; */ - template + export template using next_to_iter = detail_next_to_iter::next_to_iter_impl; /** @@ -240,7 +240,7 @@ namespace dice::template_library { * // Enables operator+= (and operator+ **if Iter is copy-constructible**) * { iter.nth_back(size_t{off}) } -> std::optional; */ - template + export template using next_back_to_reverse_iter = detail_next_to_iter::next_to_iter_impl; @@ -282,7 +282,7 @@ namespace dice::template_library { * // Enables sized_range (size(), empty(), operator bool()) for the range **if Iter is copy-constructible**. * { iter.remaining() } -> std::convertible_to; */ - template + export template struct next_to_range { using iterator = next_to_iter; using sentinel = typename iterator::sentinel; @@ -428,7 +428,7 @@ namespace dice::template_library { * // Enables sized_range (size(), empty(), operator bool()) for the view. * { iter.remaining() } -> std::convertible_to; */ - template requires (std::is_copy_constructible_v) + export template requires (std::is_copy_constructible_v) struct next_to_view : std::ranges::view_base { using iterator = next_to_iter; using sentinel = typename iterator::sentinel; @@ -553,6 +553,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - - -#endif // DICE_TEMPLATELIBRARY_NEXTTORANGE_HPP diff --git a/include/dice/template-library/opt_minmax.hpp b/src/dice/template-library/opt_minmax.cppm similarity index 91% rename from include/dice/template-library/opt_minmax.hpp rename to src/dice/template-library/opt_minmax.cppm index 71f7406..afffb59 100644 --- a/include/dice/template-library/opt_minmax.hpp +++ b/src/dice/template-library/opt_minmax.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATE_LIBRARY_OPT_MINMAX_HPP -#define DICE_TEMPLATE_LIBRARY_OPT_MINMAX_HPP - +module; #include #include #include @@ -8,13 +6,16 @@ #include +export module dice.template_library:opt_minmax; +export import :ranges; + namespace dice::template_library { /** * Result type for opt_minmax holding both the minimum and maximum. * @tparam T the value type */ - template + export template struct opt_minmax_result { T min; T max; @@ -132,12 +133,12 @@ namespace dice::template_library * @þaram cmp comparator * @return std::optional containing the minimum, or std::nullopt if the range is empty or all elements are nullopt */ - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_min_element, detail_opt_min_max::opt_min_element_impl, std::ranges::less); + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_min_element, detail_opt_min_max::opt_min_element_impl, std::ranges::less, export); /** * @return the minimum of the given arguments, treating std::nullopt as "no value". */ - template> + export template> [[nodiscard]] constexpr std::optional opt_min(std::optional const &a, std::optional const &b, Cmp cmp = {}) { if (!a.has_value()) { return b; @@ -152,7 +153,7 @@ namespace dice::template_library /** * @return the minimum of the given elements in the initializer list, treating std::nullopt as "no value". */ - template> + export template> [[nodiscard]] constexpr std::optional opt_min(std::initializer_list> ilist, Cmp cmp = {}) { return opt_min_element(ilist, cmp); } @@ -165,13 +166,13 @@ namespace dice::template_library * @param cmp comparator defining the less-than relation * @return std::optional containing the maximum, or std::nullopt if the range is empty or all elements are nullopt */ - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_max_element, detail_opt_min_max::opt_max_element_impl, std::ranges::less); + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_max_element, detail_opt_min_max::opt_max_element_impl, std::ranges::less, export); /** * @return the maximum of the given arguments, treating std::nullopt as "no value". */ - template> + export template> [[nodiscard]] constexpr std::optional opt_max(std::optional const &a, std::optional const &b, Cmp cmp = {}) { if (!a.has_value()) { return b; @@ -186,7 +187,7 @@ namespace dice::template_library /** * @return the maximum of the given elements in the initializer list, treating std::nullopt as "no value". */ - template> + export template> [[nodiscard]] constexpr std::optional opt_max(std::initializer_list> ilist, Cmp cmp = {}) { return opt_max_element(ilist, cmp); } @@ -198,7 +199,7 @@ namespace dice::template_library * @param cmp comparator * @return opt_minmax_result containing min and max, or nullopt if the range is empty or all elements are nullopt */ - DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_minmax_element, detail_opt_min_max::opt_minmax_element_impl, std::ranges::less); + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(opt_minmax_element, detail_opt_min_max::opt_minmax_element_impl, std::ranges::less, export); /** @@ -208,7 +209,7 @@ namespace dice::template_library * @param cmp comparator * @return opt_minmax_result containing min and max, or nullopt if all are empty */ - template> + export template> [[nodiscard]] constexpr std::optional> opt_minmax(std::initializer_list> ilist, Cmp cmp = {}) { return opt_minmax_element(ilist, cmp); } @@ -221,11 +222,9 @@ namespace dice::template_library * @param cmp comparator * @return opt_minmax_result containing min and max, or nullopt if all are empty */ - template> + export template> [[nodiscard]] constexpr std::optional> opt_minmax(std::optional const &a, std::optional const &b, Cmp cmp = {}) { return opt_minmax({a, b}, cmp); } } // namespace dice::template_library - -#endif // DICE_TEMPLATE_LIBRARY_OPT_MINMAX_HPP diff --git a/include/dice/template-library/overloaded.hpp b/src/dice/template-library/overloaded.cppm similarity index 81% rename from include/dice/template-library/overloaded.hpp rename to src/dice/template-library/overloaded.cppm index 8020e9d..096bdc1 100644 --- a/include/dice/template-library/overloaded.hpp +++ b/src/dice/template-library/overloaded.cppm @@ -1,9 +1,9 @@ -#ifndef DICE_TEMPLATE_LIBRARY_OVERLOADED_HPP -#define DICE_TEMPLATE_LIBRARY_OVERLOADED_HPP - +module; #include -namespace dice::template_library { +export module dice.template_library:overloaded; + +export namespace dice::template_library { /** * A utility struct that creates an overload set on-the-fly out of many functions (Fs...). @@ -26,5 +26,3 @@ namespace dice::template_library { } } // namespace dice::template_library - -#endif // DICE_TEMPLATE_LIBRARY_OVERLOADED_HPP diff --git a/include/dice/template-library/pointer_tag_pair.hpp b/src/dice/template-library/pointer_tag_pair.cppm similarity index 75% rename from include/dice/template-library/pointer_tag_pair.hpp rename to src/dice/template-library/pointer_tag_pair.cppm index 5bc1ab5..8a1d9ad 100644 --- a/include/dice/template-library/pointer_tag_pair.hpp +++ b/src/dice/template-library/pointer_tag_pair.cppm @@ -1,14 +1,15 @@ -#ifndef DICE_TEMPLATE_LIBRARY_POINTERTAGPAIR_HPP -#define DICE_TEMPLATE_LIBRARY_POINTERTAGPAIR_HPP - +module; #include #include #include #include #include #include +#include + +export module dice.template_library:pointer_tag_pair; -#include +export import :type_traits; namespace dice::template_library { namespace detail_pointer_tag_pair { @@ -35,7 +36,7 @@ namespace dice::template_library { } } // namespace detail_pointer_tag_pair - template()> struct pointer_tag_pair { @@ -104,7 +105,7 @@ namespace dice::template_library { constexpr std::strong_ordering operator<=>(pointer_tag_pair const &other) const noexcept = default; }; - template + export template constexpr std::tuple_element_t> get(pointer_tag_pair const pointer) { if constexpr (I == 0) { @@ -115,34 +116,34 @@ namespace dice::template_library { } } // namespace dice::template_library -template -struct std::tuple_size > { - static constexpr size_t value = 2; -}; - -template -struct std::tuple_size const> { - static constexpr size_t value = 2; -}; - -template -struct std::tuple_element<0, dice::template_library::pointer_tag_pair > { - using type = T *; -}; - -template -struct std::tuple_element<1, dice::template_library::pointer_tag_pair > { - using type = Tag; -}; - -template -struct std::tuple_element<0, dice::template_library::pointer_tag_pair const> { - using type = T *; -}; - -template -struct std::tuple_element<1, dice::template_library::pointer_tag_pair const> { - using type = Tag; -}; - -#endif // DICE_TEMPLATE_LIBRARY_POINTERTAGPAIR_HPP +export { + template + struct std::tuple_size> { + static constexpr size_t value = 2; + }; + + template + struct std::tuple_size const> { + static constexpr size_t value = 2; + }; + + template + struct std::tuple_element<0, dice::template_library::pointer_tag_pair> { + using type = T *; + }; + + template + struct std::tuple_element<1, dice::template_library::pointer_tag_pair> { + using type = Tag; + }; + + template + struct std::tuple_element<0, dice::template_library::pointer_tag_pair const> { + using type = T *; + }; + + template + struct std::tuple_element<1, dice::template_library::pointer_tag_pair const> { + using type = Tag; + }; +} diff --git a/include/dice/template-library/polymorphic_allocator.hpp b/src/dice/template-library/polymorphic_allocator.cppm similarity index 98% rename from include/dice/template-library/polymorphic_allocator.hpp rename to src/dice/template-library/polymorphic_allocator.cppm index 9046ac3..e1bc84b 100644 --- a/include/dice/template-library/polymorphic_allocator.hpp +++ b/src/dice/template-library/polymorphic_allocator.cppm @@ -1,9 +1,4 @@ -#ifndef DICE_TEMPLATE_LIBRARY_POLYMORPHICALLOCATOR_HPP -#define DICE_TEMPLATE_LIBRARY_POLYMORPHICALLOCATOR_HPP - -#include - - +module; #include #include #include @@ -12,6 +7,9 @@ #if __has_include() #include #endif // __has_include() +export module dice.template_library:polymorphic_allocator; + +export import :variant2; namespace dice::template_library { namespace detail_pmr { @@ -105,7 +103,7 @@ namespace dice::template_library { * @tparam T the type of object this allocator allocates * @tparam Allocators a list of the different allocator templates */ - template typename ...Allocators> + export template typename ...Allocators> struct polymorphic_allocator { static_assert(sizeof...(Allocators) > 0, "Need at least one allocator"); @@ -324,7 +322,7 @@ namespace dice::template_library { * @brief Wraps and `std::allocator`-like type, but returns boost::interprocess::offset_ptr instead of raw pointers * @tparam T type to allocate */ - template typename Allocator = std::allocator> + export template typename Allocator = std::allocator> struct offset_ptr_stl_allocator { using value_type = T; using pointer = boost::interprocess::offset_ptr; @@ -412,5 +410,3 @@ namespace dice::template_library { #endif // __has_include() }// namespace dice::template_library - -#endif//DICE_TEMPLATE_LIBRARY_POLYMORPHICALLOCATOR_HPP diff --git a/include/dice/template-library/pool_allocator.hpp b/src/dice/template-library/pool_allocator.cppm similarity index 96% rename from include/dice/template-library/pool_allocator.hpp rename to src/dice/template-library/pool_allocator.cppm index 65afc3f..132da96 100644 --- a/include/dice/template-library/pool_allocator.hpp +++ b/src/dice/template-library/pool_allocator.cppm @@ -1,7 +1,8 @@ -#ifndef DICE_TEMPLATELIBRARY_POOLALLOCATOR_HPP -#define DICE_TEMPLATELIBRARY_POOLALLOCATOR_HPP - +module; +#if __has_include() #include +#define HAS_BOOST_INTERPROCESS_OFFSET +#endif #include #include @@ -9,7 +10,10 @@ #include #include -namespace dice::template_library { +export module dice.template_library:pool_allocator; + +#ifdef HAS_BOOST_INTERPROCESS_OFFSET +export namespace dice::template_library { /** * A memory pool or arena that is efficient for allocations which are smaller or equal in size @@ -197,6 +201,4 @@ namespace dice::template_library { }; } // namespace dice::template_library - - -#endif // DICE_TEMPLATELIBRARY_POOLALLOCATOR_HPP +#endif diff --git a/src/dice/template-library/ranges.cppm b/src/dice/template-library/ranges.cppm new file mode 100644 index 0000000..50a43c5 --- /dev/null +++ b/src/dice/template-library/ranges.cppm @@ -0,0 +1,657 @@ +module; +#include + +#include +#include +#include +#include +#include +#include + +export module dice.template_library:ranges; + +export import :next_to_range; + +namespace dice::template_library { + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_of, std::ranges::all_of, std::ranges::equal_to, export); + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(any_of, std::ranges::any_of, std::ranges::equal_to, export); + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(none_of, std::ranges::none_of, std::ranges::equal_to, export); +}// namespace dice::template_library + +// empty / non_empty terminal algorithm +namespace dice::template_library { + namespace ranges_algo_detail { + struct empty_fn { + template S> + constexpr bool operator()(I first, S last) const { + std::ranges::subrange range{std::move(first), std::move(last)}; + static_assert(requires { std::ranges::empty(range); }, "std::ranges::empty requires a forward range as it might otherwise be expensive to materialize the first element."); + return std::ranges::empty(range); + } + + template + constexpr bool operator()(R &&range) const { + static_assert(requires { std::ranges::empty(range); }, "std::ranges::empty requires a forward range as it might otherwise be expensive to materialize the first element."); + return std::ranges::empty(std::forward(range)); + } + + template + friend constexpr bool operator|(R &&range, empty_fn const &self) { + return self(std::forward(range)); + } + }; + + struct non_empty_fn { + template S> + constexpr bool operator()(I first, S last) const { + return !empty_fn{}(std::move(first), std::move(last)); + } + + template + constexpr bool operator()(R &&range) const { + return !empty_fn{}(std::forward(range)); + } + + template + friend constexpr bool operator|(R &&range, non_empty_fn const &self) { + return self(std::forward(range)); + } + }; + }// namespace ranges_algo_detail + + /** + * @brief Checks if a range is empty. + * + * This is a pipeable, terminal algorithm. It uses `std::ranges::empty` if available, + * otherwise it falls back to comparing `cbegin()` and `cend()`. + * + * @return A closure that returns true if the range is empty otherwise false. + */ + export inline constexpr ranges_algo_detail::empty_fn empty{}; + + /** + * @brief Checks if a range is not empty. + * + * This is a pipeable, terminal algorithm and the logical negation of `dtl::empty`. + * + * @return A closure that returns true if the range has at least one element otherwise false. + */ + export inline constexpr ranges_algo_detail::non_empty_fn non_empty{}; + +}// namespace dice::template_library + +// remove_element adaptor +namespace dice::template_library { + namespace ranges_algo_detail { + template + constexpr std::ranges::view auto remove_element_impl(R &&range, T remove_value, Pred pred = {}) { + return std::forward(range) + | std::views::filter([remove_value = std::move(remove_value), pred = std::move(pred)](auto const &element) { + return !std::invoke(pred, element, remove_value); + }); + } + + template + struct remove_element_pipeline { + private: + T value_; + Pred pred_; + + public: + template + constexpr remove_element_pipeline(V &&value, P &&pred) + : value_{std::forward(value)}, pred_{std::forward

(pred)} { + } + + template + friend constexpr std::ranges::view auto operator|(R &&range, remove_element_pipeline const &self) { + return remove_element_impl(std::forward(range), self.value_, self.pred_); + } + }; + + struct remove_element_fn { + template + constexpr auto operator()(T remove_value, Pred pred = {}) const { + return remove_element_pipeline{std::move(remove_value), std::move(pred)}; + } + }; + }// namespace ranges_algo_detail + + /** + * Creates a lazy, pipeable view of a range that excludes elements matching a given value. This adaptor does not modify the source range. + * + * @param value The value to filter out of the source range. + * @param pred Optional binary predicate for comparison. Defaults to `std::ranges::equal_to`. + * @return A range adaptor closure. + * + * @note This view is deprecated because it is not possible to make it callable as a regular function and pipelineable + * at the same time due to overload resolution issues with ranges of ranges. + * Additionally, this is just a `std::views::filter([remove_value](auto const &x) { return x != remove_value });`, use that instead. + */ + export [[deprecated("Use std::views::filter")]] inline constexpr ranges_algo_detail::remove_element_fn remove_element; + +}// namespace dice::template_library + +// all_equal adaptor +namespace dice::template_library { + namespace ranges_algo_detail { + template S, typename Pred = std::ranges::equal_to> + requires (std::copyable>) + bool all_equal_impl(I first, S last, Pred pred) { + if (first == last) { + return true; + } + + auto const first_element = *first; + ++first; + + // Check if all subsequent elements in the range match the first one. + return std::ranges::subrange(first, last) + | dice::template_library::all_of([&](auto const ¤t_element) { + return std::invoke(pred, current_element, first_element); + }); + } + }// namespace ranges_algo_detail + + /** + * @brief Checks if all elements in a range are equal to each other. + * + * This is a pipeable, terminal algorithm that returns a boolean. Elements must be copyable for this to work. + * + * @param pred Optional binary predicate for comparison. Defaults to `std::ranges::equal_to`. + * @return true if all elements in the range are equal, otherwise false. + */ + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_equal, ranges_algo_detail::all_equal_impl, std::ranges::equal_to, export); +}// namespace dice::template_library + +// unique adaptor +namespace dice::template_library { + namespace ranges_algo_detail { + + template + concept unordered_set_elem = std::equality_comparable && requires (T const &elem) { + { std::hash{}(elem) } -> std::convertible_to; + }; + + template + concept set_elem = std::strict_weak_order, T, T>; + + template + requires std::ranges::view + struct unique_view : std::ranges::view_interface> { + struct iterator; + using sentinel = std::default_sentinel_t; + + private: + R base_; + + public: + explicit constexpr unique_view(R const &base) : base_{base} {} + explicit constexpr unique_view(R &&base) : base_{std::move(base)} {} + + constexpr iterator begin() { + return iterator{*this}; + } + + constexpr sentinel end() const noexcept { + return std::default_sentinel; + } + }; + + template + requires std::ranges::view + struct unique_view::iterator { + using iterator_category = std::input_iterator_tag; + using value_type = std::ranges::range_value_t; + using difference_type = std::ranges::range_difference_t; + + private: + using set_value_type = std::remove_cvref_t>; + + static_assert(std::copy_constructible, + "The value type for unique must be copy-constructible."); + + static_assert(set_elem || unordered_set_elem, + "The value type must be either hashable and equality comparable, or support less than."); + + using set_type = std::conditional_t< + unordered_set_elem,// prioritize unordered_set + std::unordered_set, + std::set>; + + set_type seen_; + std::ranges::iterator_t current_; + [[no_unique_address]] std::ranges::sentinel_t end_; + + void find_next_unique() { + while (current_ != end_) { + if (seen_.insert(*current_).second) { + break; + } + ++current_; + } + } + + public: + explicit constexpr iterator(unique_view &parent) + : seen_{}, + current_{std::ranges::begin(parent.base_)}, + end_{std::ranges::end(parent.base_)} { + find_next_unique(); + } + + constexpr decltype(auto) operator*() const { + return *current_; + } + + constexpr iterator &operator++() { + ++current_; + find_next_unique(); + return *this; + } + + constexpr void operator++(int) { + ++*this; + } + + friend constexpr bool operator==(iterator const &self, std::default_sentinel_t) { + return self.current_ == self.end_; + } + + friend constexpr bool operator==(std::default_sentinel_t sent, iterator const &self) { + return self == sent; + } + }; + + struct unique_fn { + template + constexpr auto operator()(R &&r) const { + return unique_view(std::views::all(std::forward(r))); + } + + template + friend constexpr auto operator|(R &&r, unique_fn const &self) { + return self(std::forward(r)); + } + }; + }// namespace ranges_algo_detail + + /** + * @brief A range adaptor that produces a view containing the first occurrence of each element from an underlying range. + * + * This adaptor is lazy and preserves the relative order of the unique elements. It automatically uses a hash set + * for tracking if the element type is hashable, otherwise it falls back to a sorted set. + * + * @return A lazy view containing the unique elements. + */ + export [[deprecated("This view is inefficient and will be removed. Manually construct a set, or use a combination of chunk_by and transform " + "on sorted ranges.")]] inline constexpr ranges_algo_detail::unique_fn unique; + +}// namespace dice::template_library + + +namespace dice::template_library { + + export template + concept step_for = std::is_default_constructible_v && requires (T start, T const stop, S step) { + { start <= stop } -> std::convertible_to; + { start >= stop } -> std::convertible_to; + + start += step; + }; + + namespace ranges_algo_detail { + /** + * range generator (python-like iota with step) implemented as a rust-like next() iterator + * + * @tparam T range return type + * @tparam S step type for range (can also be a signed type even though T is unsigned) + */ + template S> + struct range_iterator { + using value_type = T; + + private: + T current_; + T stop_; + S step_; + + public: + range_iterator() noexcept + requires (std::is_default_constructible_v && std::is_constructible_v) + : current_{}, + stop_{}, + step_{1} { + } + + explicit constexpr range_iterator(T start, T stop, S step) + : current_{start}, stop_{stop}, step_{step} { + if (step == S{}) [[unlikely]] { + throw std::invalid_argument{"range: step must not be the zero element/the additive identity"}; + } + } + + [[nodiscard]] constexpr std::optional next() noexcept { + if (step_ > S{}) { + if (current_ >= stop_) { + return std::nullopt; + } + } else { + if (current_ <= stop_) { + return std::nullopt; + } + } + + return std::exchange(current_, current_ + step_); + } + + [[nodiscard]] constexpr size_t remaining() const noexcept + requires (std::integral && std::integral) + { + if (current_ <= stop_) { + // forward + if (step_ < S{}) { + // wrong direction + return 0; + } + + return static_cast((stop_ - current_ + step_ - 1) / step_); + } else { + // backward + if (step_ > S{}) { + // wrong direction + return 0; + } + + return static_cast((current_ - stop_ + -step_ - 1) / -step_); + } + } + + [[nodiscard]] constexpr std::optional nth(size_t off) noexcept + requires (std::integral && std::integral) + { + auto const rem = remaining(); + if (off >= rem) { + current_ = stop_; + return std::nullopt; + } + + current_ += static_cast(off) * step_; + return next(); + } + + [[nodiscard]] constexpr std::optional next_back() noexcept + requires (std::integral && std::integral) + { + if (step_ > S{}) { + if (current_ >= stop_) { + return std::nullopt; + } + stop_ -= step_; + return stop_; + } else { + if (current_ <= stop_) { + return std::nullopt; + } + stop_ -= step_; + return stop_; + } + } + + [[nodiscard]] constexpr std::optional nth_back(size_t off) noexcept + requires (std::integral && std::integral) + { + auto const rem = remaining(); + if (off >= rem) { + stop_ = current_; + return std::nullopt; + } + + stop_ -= static_cast(off) * step_; + return next_back(); + } + }; + }// namespace ranges_algo_detail + + export template + using range_view = next_to_view>; + + /** + * @brief A lazy view that generates a sequence of numbers, similar to Python's range(). + * + * This view can be used with one, two, or three arguments: + * - `range(stop)`: Generates [0,stop). + * - `range(start, stop)`: Generates [start,stop). + * - `range(start, stop, step)`: Generates numbers from start, incrementing by step, until stop is met or passed. + */ + export template + [[nodiscard]] constexpr range_view range(T start, T stop, S step) { + return range_view{start, stop, step}; + } + + export template + requires (std::is_constructible_v && step_for) + [[nodiscard]] constexpr range_view range(T start, T stop) { + return range_view{start, stop, T(1)}; + } + + export template + requires (std::is_default_constructible_v && std::is_constructible_v) + [[nodiscard]] constexpr range_view range(T stop) { + return range_view{T{}, stop, T(1)}; + } + +}// namespace dice::template_library + +// all_distinct terminal algorithm +namespace dice::template_library { + namespace ranges_algo_detail { + template S, typename Pred = std::ranges::equal_to> + [[nodiscard]] constexpr bool all_distinct_impl(I first, S last, Pred pred) { + using value_type = std::remove_cvref_t>; + static_assert(unordered_set_elem || (set_elem && std::is_same_v), + "The elements of the consumed range are neither compatible with std::unordered_set nor with std::set."); + + if (first == last) { + return true; + } + + auto seen = [&] { + if constexpr (unordered_set_elem) { + return std::unordered_set, Pred>{1, {}, std::move(pred)}; + } else { + return std::set{}; + } + }(); + + for (; first != last; ++first) { + if (!seen.insert(*first).second) { + return false; + } + } + return true; + } + + template S, typename Pred = std::ranges::equal_to> + [[nodiscard]] constexpr bool all_distinct_sorted_impl(I first, S last, Pred pred) { + return std::ranges::adjacent_find(first, last, std::move(pred)) == last; + } + } // namespace ranges_algo_detail + + /** + * @brief Checks if all elements in a range are distinct from one another. + * + * This is a pipeable, terminal algorithm that returns a boolean. + * - When called without arguments, it uses a hash set if the type is hashable, otherwise it + * falls back to a sorted set if the type is comparable. + * - When called with a custom equality predicate, it requires the type to be hashable. + * + * @param pred Optional binary predicate for equality comparison. Defaults to `std::ranges::equal_to`. + * @return true if all elements are distinct, otherwise false. + */ + DTL_DEFINE_SINGLE_FUNC_BASED_RANGE_ALGO(all_distinct, + ranges_algo_detail::all_distinct_impl, + std::ranges::equal_to, + export [[deprecated("This algorithm is inefficient and will be removed. Manually construct a set, or use " + "std::ranges::adjacent_find in sorted ranges to check for distinctness.")]]); +} // namespace dice::template_library + +// is_sorted_unique terminal algorithm +namespace dice::template_library { + namespace ranges_algo_detail { + template S, typename Cmp, typename Proj> + requires (std::indirect_strict_weak_order>) + constexpr bool is_sorted_unique_impl(I first, S last, Cmp cmp, Proj proj) { + if (first == last) { + return true; + } + + auto it = first; + while (++it != last) { + // We require that 'prev' is strictly less than 'curr'. + // cmp(a, b) ~ a < b + // <-> !cmp(a, b) ~ a >= b + if (!std::invoke(cmp, std::invoke(proj, *first), std::invoke(proj, *it))) { + return false; + } + first = it; + } + return true; + } + + template + struct is_sorted_unique_pipeline { + private: + [[no_unique_address]] Cmp cmp_; + [[no_unique_address]] Proj proj_; + + public: + is_sorted_unique_pipeline(Cmp cmp, Proj proj) + : cmp_{std::move(cmp)}, proj_{std::move(proj)} { + } + + template + [[nodiscard]] friend constexpr bool operator|(R &&range, is_sorted_unique_pipeline const &self) { + return is_sorted_unique_impl(std::ranges::begin(range), std::ranges::end(range), self.cmp_, self.proj_); + } + }; + + struct is_sorted_unique_fn { + /** + * Return true iff the given range is sorted and there are no duplicates. + * + * @param range range to check + * @param cmp comparator + * @param proj projection + */ + template + [[nodiscard]] constexpr bool operator()(R &&range, Cmp cmp = {}, Proj proj = {}) const { + return is_sorted_unique_impl(std::ranges::begin(range), std::ranges::end(range), std::move(cmp), std::move(proj)); + } + + /** + * Return true iff the given range is sorted and there are no duplicates. + * + * @param first iterator to start of range + * @param last sentinel for range + * @param cmp comparator + * @param proj projection + * @return + */ + template S, typename Cmp = std::ranges::less, typename Proj = std::identity> + [[nodiscard]] constexpr bool operator()(I first, S last, Cmp cmp = {}, Proj proj = {}) const { + return is_sorted_unique_impl(std::move(first), std::move(last), std::move(cmp), std::move(proj)); + } + + /** + * Pipeline overload for is_strictly_sorted + */ + template + requires (!std::ranges::input_range && !std::input_iterator) + [[nodiscard]] constexpr auto operator()(Cmp cmp = {}, Proj proj = {}) const { + return is_sorted_unique_pipeline{std::move(cmp), std::move(proj)}; + } + }; + } // namespace ranges_algo_detail + + /** + * Return true iff the given range is sorted and there are no duplicates. + * + * @param range or first+last range to check + * @param cmp comparator + * @param proj projection + */ + export inline constexpr ranges_algo_detail::is_sorted_unique_fn is_sorted_unique; + + namespace ranges_algo_detail { + struct lexicographical_compare_three_way_fn { + /** + * Lexicographically compares two ranges range1 and range2 + * + * @param range1 first range + * @param range2 second range + * @param cmp three-way comparator + * @param proj1 projection for first range + * @param proj2 projection for second range + * @return lexicographical three-way compare result of the two ranges + */ + template + [[nodiscard]] constexpr auto operator()(R1 &&range1, R2 &&range2, Cmp cmp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { + return lexicographical_compare_three_way_fn{}(std::ranges::begin(range1), std::ranges::end(range1), std::ranges::begin(range2), std::ranges::end(range2), cmp, proj1, proj2); + } + + /** + * Lexicographically compares two ranges [first1, last1) and [first2, last2) using three-way comparison. + * + * @param first1 iterator to start of first range + * @param last1 sentinel for first range + * @param first2 iterator to start of second range + * @param last2 sentinel for second range + * @param cmp three-way comparator + * @param proj1 projection for first range + * @param proj2 projection for second range + * @return lexicographical three-way compare result of the two ranges + */ + template S1, std::input_iterator I2, std::sentinel_for S2, typename Proj1 = std::identity, typename Proj2 = std::identity, typename Cmp = std::compare_three_way> + [[nodiscard]] constexpr auto operator()(I1 first1, S1 last1, I2 first2, S2 last2, Cmp cmp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { + using proj1_res = std::indirect_result_t; + using proj2_res = std::indirect_result_t; + using cmp_cat = std::invoke_result_t; + + while (first1 != last1 && first2 != last2) { + auto const res = std::invoke(cmp, std::invoke(proj1, *first1), std::invoke(proj2, *first2)); + if (res != 0) { + return res; + } + + ++first1; + ++first2; + } + + bool const exhaust1 = first1 == last1; + bool const exhaust2 = first2 == last2; + + if (exhaust1 && exhaust2) { + return cmp_cat{std::strong_ordering::equal}; + } + if (exhaust1) { + return cmp_cat{std::strong_ordering::less}; + } + return cmp_cat{std::strong_ordering::greater}; + } + }; + } // namespace ranges_algo_detail + + /** + * Lexicographically compares two ranges range1/[first1, last1) and range2/[first2, last2) using three-way comparison. + * + * @param range1 or first1+last1 first range + * @param range2 or first2+last2 second range + * @param cmp three-way comparator + * @param proj1 projection for first range + * @param proj2 projection for second range + * @return lexicographical three-way compare result of the two ranges + */ + export inline constexpr ranges_algo_detail::lexicographical_compare_three_way_fn lexicographical_compare_three_way; + +}// namespace dice::template_library diff --git a/include/dice/template-library/shared_mutex.hpp b/src/dice/template-library/shared_mutex.cppm similarity index 97% rename from include/dice/template-library/shared_mutex.hpp rename to src/dice/template-library/shared_mutex.cppm index 52b43cd..0bc43c5 100644 --- a/include/dice/template-library/shared_mutex.hpp +++ b/src/dice/template-library/shared_mutex.cppm @@ -1,13 +1,13 @@ -#ifndef DICE_TEMPLATELIBRARY_SHAREDMUTEX_HPP -#define DICE_TEMPLATELIBRARY_SHAREDMUTEX_HPP - +module; #include #include #include #include #include -namespace dice::template_library { +export module dice.template_library:shared_mutex; + +export namespace dice::template_library { template struct shared_mutex; @@ -159,5 +159,3 @@ namespace dice::template_library { }; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_SHAREDMUTEX_HPP diff --git a/include/dice/template-library/standard_layout_tuple.hpp b/src/dice/template-library/standard_layout_tuple.cppm similarity index 93% rename from include/dice/template-library/standard_layout_tuple.hpp rename to src/dice/template-library/standard_layout_tuple.cppm index e0a965e..ec15fcf 100644 --- a/include/dice/template-library/standard_layout_tuple.hpp +++ b/src/dice/template-library/standard_layout_tuple.cppm @@ -1,15 +1,15 @@ -#ifndef DICE_TEMPLATELIBRARY_STANDARDLAYOUTTUPLE_HPP -#define DICE_TEMPLATELIBRARY_STANDARDLAYOUTTUPLE_HPP - -#include -#include - +module; #include #include #include #include -namespace dice::template_library { +export module dice.template_library:standard_layout_tuple; + +export import :type_list; +export import :type_traits; + +export namespace dice::template_library { /** * A tag type to tell a tuple to construct all fields with the same arguments. @@ -146,13 +146,11 @@ namespace dice::template_library { } // namespace dice::template_library -template +export template struct std::tuple_size> : std::integral_constant { }; -template +export template struct std::tuple_element> { using type = dice::template_library::type_list::nth_t, ix>; }; - -#endif // DICE_TEMPLATELIBRARY_STANDARDLAYOUTTUPLE_HPP diff --git a/include/dice/template-library/static_string.hpp b/src/dice/template-library/static_string.cppm similarity index 98% rename from include/dice/template-library/static_string.hpp rename to src/dice/template-library/static_string.cppm index c05fa48..3fc72a4 100644 --- a/include/dice/template-library/static_string.hpp +++ b/src/dice/template-library/static_string.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_CONSTSTRING_HPP -#define DICE_TEMPLATELIBRARY_CONSTSTRING_HPP - +module; #include #include #include @@ -8,7 +6,9 @@ #include #include -namespace dice::template_library { +export module dice.template_library:static_string; + +export namespace dice::template_library { /** * A constant-size (i.e. non-growing), heap-allocated string type @@ -249,5 +249,3 @@ namespace dice::template_library { using static_u32string = basic_static_string; } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_CONSTSTRING_HPP \ No newline at end of file diff --git a/include/dice/template-library/stdint.hpp b/src/dice/template-library/stdint.cppm similarity index 93% rename from include/dice/template-library/stdint.hpp rename to src/dice/template-library/stdint.cppm index fc381b7..8f96608 100644 --- a/include/dice/template-library/stdint.hpp +++ b/src/dice/template-library/stdint.cppm @@ -1,10 +1,10 @@ -#ifndef DICE_TEMPLATELIBRARY_STDINT_HPP -#define DICE_TEMPLATELIBRARY_STDINT_HPP - +module; #include #include -namespace dice::template_library::literals { +export module dice.template_library.literals; + +export namespace dice::template_library::literals { constexpr uint8_t operator""_u8(unsigned long long value) noexcept { return static_cast(value); @@ -67,5 +67,3 @@ namespace dice::template_library::literals { } } // namespace dice::template_library::literals - -#endif // DICE_TEMPLATELIBRARY_STDINT_HPP diff --git a/include/dice/template-library/switch_cases.hpp b/src/dice/template-library/switch_cases.cppm similarity index 94% rename from include/dice/template-library/switch_cases.hpp rename to src/dice/template-library/switch_cases.cppm index dbea69e..9b67dff 100644 --- a/include/dice/template-library/switch_cases.hpp +++ b/src/dice/template-library/switch_cases.cppm @@ -1,12 +1,12 @@ -#ifndef HYPERTRIE_SWITCHTEMPLATEFUNCTIONS_HPP -#define HYPERTRIE_SWITCHTEMPLATEFUNCTIONS_HPP - +module; #include #include #include #include #include +export module dice.template_library:switch_cases; + namespace dice::template_library { namespace detail_switch_cases { @@ -52,7 +52,7 @@ namespace dice::template_library { * @param default_function the default fallback if condition is out of range [min,max) spanned b first, last * @return The value returned from the switch case */ - template + export template constexpr decltype(auto) switch_cases(decltype(first) condition, F &&cases_function, D &&default_function) { constexpr decltype(first) min = std::min(first, last); @@ -82,7 +82,7 @@ namespace dice::template_library { * @param default_function the default fallback if condition is out of range [min,max) spanned b first, last * @return The value returned from the switch case */ - template + export template constexpr decltype(auto) switch_cases(decltype(first) condition, F &&cases_function) { return switch_cases(condition, std::forward(cases_function), detail_switch_cases::unreachable); } @@ -100,7 +100,7 @@ namespace dice::template_library { * @param default_function the default fallback if condition is out of range [min,max) spanned b first, last * @return The value returned from the switch case */ - template + export template constexpr decltype(auto) switch_cases(decltype(last) condition, F &&cases_function, D &&default_function) { return switch_cases(condition, std::forward(cases_function), std::forward(default_function)); } @@ -119,7 +119,7 @@ namespace dice::template_library { * @param default_function the default fallback if condition is out of range [min,max) spanned b first, last * @return The value returned from the switch case */ - template + export template constexpr decltype(auto) switch_cases(decltype(last) condition, F &&cases_function) { return switch_cases(condition, std::forward(cases_function), detail_switch_cases::unreachable); } @@ -131,7 +131,7 @@ namespace dice::template_library { * @param cases_function the switch function template or lambda * @return The value returned from the cases_function */ - template + export template constexpr decltype(auto) switch_bool(bool condition, F &&cases_function) { if (condition) { return std::invoke(std::forward(cases_function), std::bool_constant{}); @@ -140,5 +140,3 @@ namespace dice::template_library { return std::invoke(std::forward(cases_function), std::bool_constant{}); } }// namespace dice::template_library - -#endif//HYPERTRIE_SWITCHTEMPLATEFUNCTIONS_HPP diff --git a/include/dice/template-library/tuple_algorithm.hpp b/src/dice/template-library/tuple_algorithm.cppm similarity index 92% rename from include/dice/template-library/tuple_algorithm.hpp rename to src/dice/template-library/tuple_algorithm.cppm index 2c01327..264bfd9 100644 --- a/include/dice/template-library/tuple_algorithm.hpp +++ b/src/dice/template-library/tuple_algorithm.cppm @@ -1,11 +1,11 @@ -#ifndef DICE_TEMPLATE_LIBRARY_TUPLEALGORITHM_HPP -#define DICE_TEMPLATE_LIBRARY_TUPLEALGORITHM_HPP - +module; #include #include #include #include +export module dice.template_library:tuple_algo; + namespace dice::template_library { namespace tuple_algo_detail { @@ -62,7 +62,7 @@ namespace dice::template_library { * @param f binop for accumulator, tuple-element * @return the final value of the accumulator */ - template + export template constexpr Acc tuple_fold(Tuple const &tuple, Acc &&init, FoldF &&f) noexcept { return tuple_algo_detail::tuple_fold_impl(std::make_index_sequence>>{}, tuple, std::forward(init), std::forward(f)); } @@ -76,7 +76,7 @@ namespace dice::template_library { * @param f partially templated binop for tuple-type and accumulator * @return the final value of the accumulator */ - template + export template constexpr Acc tuple_type_fold(Acc &&init, FoldF &&f) noexcept { return tuple_algo_detail::tuple_type_fold_impl(std::make_index_sequence>{}, std::forward(init), std::forward(f)); } @@ -88,7 +88,7 @@ namespace dice::template_library { * @param f unop to apply to each element * @return whatever the last call to f returned */ - template + export template constexpr decltype(auto) tuple_for_each(Tuple &&tuple, F &&f) { return tuple_algo_detail::tuple_for_each_impl(std::make_index_sequence>>{}, std::forward(tuple), std::forward(f)); } @@ -100,11 +100,9 @@ namespace dice::template_library { * @param f template unop to apply to each type (as f.template operator()()) * @return whatever the last call to f returned */ - template + export template constexpr decltype(auto) tuple_type_for_each(F &&f) { return tuple_algo_detail::tuple_type_for_each_impl(std::make_index_sequence>{}, std::forward(f)); } } // namespace dice::template_library - -#endif // DICE_TEMPLATE_LIBRARY_TUPLEALGORITHM_HPP diff --git a/include/dice/template-library/type_list.hpp b/src/dice/template-library/type_list.cppm similarity index 98% rename from include/dice/template-library/type_list.hpp rename to src/dice/template-library/type_list.cppm index cf843cc..a7f340f 100644 --- a/include/dice/template-library/type_list.hpp +++ b/src/dice/template-library/type_list.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_TYPELIST_HPP -#define DICE_TEMPLATELIBRARY_TYPELIST_HPP - +module; #include #include @@ -8,7 +6,9 @@ #include #include -namespace dice::template_library::type_list { +export module dice.template_library:type_list; + +export namespace dice::template_library::type_list { /** * A list of types. @@ -416,7 +416,7 @@ namespace dice::template_library::type_list { }; template - static constexpr size_t count_v = count::value; + constexpr size_t count_v = count::value; /** @@ -744,5 +744,3 @@ namespace dice::template_library::type_list { inline constexpr bool all_distinct_v = all_distinct::value; } // namespace dice::template_library::type_list - -#endif // DICE_TEMPLATELIBRARY_TYPELIST_HPP diff --git a/include/dice/template-library/type_traits.hpp b/src/dice/template-library/type_traits.cppm similarity index 69% rename from include/dice/template-library/type_traits.hpp rename to src/dice/template-library/type_traits.cppm index e68dcae..e2d94ba 100644 --- a/include/dice/template-library/type_traits.hpp +++ b/src/dice/template-library/type_traits.cppm @@ -1,10 +1,10 @@ -#ifndef DICE_TEMPLATELIBRARY_ZST_HPP -#define DICE_TEMPLATELIBRARY_ZST_HPP - +module; #include #include -namespace dice::template_library { +export module dice.template_library:type_traits; + +export namespace dice::template_library { namespace detail_zst { template struct zst_checker { @@ -166,38 +166,4 @@ namespace dice::template_library { [[nodiscard]] constexpr detail_forward_like::like_t forward_like(U &&val) noexcept { return static_cast>(val); } - -/** - * Move a value if it is either a non-const rvalue-reference or just a value (without reference qualifiers). - * - * @param expr expression to potentially move - * - * @example - * @code - * int value; - * int &ref; - * int const &cref; - * int &&rref; - * int const &&crref; - * - * DICE_MOVE_IF_VALUE(value) // moves - * DICE_MOVE_IF_VALUE(rref) // moves - * - * DICE_MOVE_IF_VALUE(ref) // does not move - * DICE_MOVE_IF_VALUE(cref) // does not move - * DICE_MOVE_IF_VALUE(crref) // does not move - * @endcode - */ -#define DICE_MOVE_IF_VALUE(expr) \ - [&] || std::is_const_v>>() \ - -> std::conditional_t<_dice_detail_no_move, decltype(expr), std::add_rvalue_reference_t>> { \ - if constexpr (_dice_detail_no_move) { \ - return expr; \ - } else { \ - return std::move(expr); \ - } \ - }() - } // namespace dice::template_library - -#endif // DICE_TEMPLATELIBRARY_ZST_HPP diff --git a/include/dice/template-library/variant2.hpp b/src/dice/template-library/variant2.cppm similarity index 96% rename from include/dice/template-library/variant2.hpp rename to src/dice/template-library/variant2.cppm index 9f672f8..0e546f3 100644 --- a/include/dice/template-library/variant2.hpp +++ b/src/dice/template-library/variant2.cppm @@ -1,6 +1,4 @@ -#ifndef DICE_TEMPLATELIBRARY_VARIANT2_HPP -#define DICE_TEMPLATELIBRARY_VARIANT2_HPP - +module; #include #include #include @@ -11,6 +9,8 @@ #include #include +export module dice.template_library:variant2; + #define DICE_TEMPLATELIBRARY_DETAIL_VARIANT2_TRY(noexcept_spec, action_block) \ if constexpr (noexcept_spec) { \ action_block \ @@ -24,12 +24,12 @@ } -namespace dice::template_library { +export namespace dice::template_library { template struct variant2; } // namespace dice::template_library -namespace std { +export namespace std { template struct variant_size<::dice::template_library::variant2> : std::integral_constant { }; @@ -163,19 +163,19 @@ namespace dice::template_library { } } // namespace detail_variant2 - using std::variant_npos; - using std::variant_alternative; - using std::variant_alternative_t; - using std::variant_size; - using std::variant_size_v; - using std::bad_variant_access; + export using std::variant_npos; + export using std::variant_alternative; + export using std::variant_alternative_t; + export using std::variant_size; + export using std::variant_size_v; + export using std::bad_variant_access; /** * An optimized version of std::variant for 2 types * @tparam T first type * @tparam U second type */ - template + export template struct variant2 { static_assert(!std::is_same_v, "Multiple occurrences of the same type are not supported"); @@ -785,7 +785,7 @@ namespace dice::template_library { friend constexpr auto detail_variant2::get_if_impl(Self &&self) noexcept -> typename detail_variant2::copy_const, std::variant_alternative_t>>::type *; }; - template + export template [[nodiscard]] constexpr bool holds_alternative(variant2 const &var) noexcept { if constexpr (std::is_same_v || std::is_same_v) { return var.index() == (std::is_same_v ? 0 : 1); @@ -795,27 +795,27 @@ namespace dice::template_library { } // overloads for get - template + export template [[nodiscard]] constexpr std::variant_alternative_t> const &get(variant2 const &var) { return detail_variant2::get_impl(var); } - template + export template [[nodiscard]] constexpr std::variant_alternative_t> &get(variant2 &var) { return detail_variant2::get_impl(var); } - template + export template [[nodiscard]] constexpr std::variant_alternative_t> const &&get(variant2 const &&var) { return detail_variant2::get_impl(std::move(var)); } - template + export template [[nodiscard]] constexpr std::variant_alternative_t> &&get(variant2 &&var) { return detail_variant2::get_impl(std::move(var)); } - template + export template [[nodiscard]] constexpr std::variant_alternative_t> const *get_if(variant2 const *var) noexcept { if (var == nullptr) { return nullptr; @@ -824,7 +824,7 @@ namespace dice::template_library { return detail_variant2::get_if_impl(*var); } - template + export template [[nodiscard]] constexpr std::variant_alternative_t> *get_if(variant2 *var) noexcept { if (var == nullptr) { return nullptr; @@ -834,27 +834,27 @@ namespace dice::template_library { } // overloads of get - template + export template [[nodiscard]] constexpr X const &get(variant2 const &var) { return detail_variant2::get_impl(var); } - template + export template [[nodiscard]] constexpr X &get(variant2 &var) { return detail_variant2::get_impl(var); } - template + export template [[nodiscard]] constexpr X const &&get(variant2 const &&var) { return detail_variant2::get_impl(std::move(var)); } - template + export template [[nodiscard]] constexpr X &&get(variant2 &&var) { return detail_variant2::get_impl(std::move(var)); } - template + export template [[nodiscard]] constexpr X const *get_if(variant2 const *var) noexcept { if (var == nullptr) { return nullptr; @@ -863,7 +863,7 @@ namespace dice::template_library { return detail_variant2::get_if_impl(*var); } - template + export template [[nodiscard]] constexpr X *get_if(variant2 *var) noexcept { if (var == nullptr) { return nullptr; @@ -874,22 +874,22 @@ namespace dice::template_library { // overloads for visit - template + export template constexpr decltype(auto) visit(F &&visitor, variant2 const &var) { return detail_variant2::visit_impl(var, std::forward(visitor)); } - template + export template constexpr decltype(auto) visit(F &&visitor, variant2 &var) { return detail_variant2::visit_impl(var, std::forward(visitor)); } - template + export template constexpr decltype(auto) visit(F &&visitor, variant2 const &&var) { return detail_variant2::visit_impl(std::move(var), std::forward(visitor)); } - template + export template constexpr decltype(auto) visit(F &&visitor, variant2 &&var) { return detail_variant2::visit_impl(std::move(var), std::forward(visitor)); } @@ -899,12 +899,12 @@ namespace dice::template_library { * if sizeof...(Ts) == 2 selects dice::template_library::variant2 * otherwise selects std::variant */ - template + export template using variant = typename detail_variant2::select_variant::type; } // namespace dice::template_library -template requires (std::formattable && std::formattable) +export template requires (std::formattable && std::formattable) struct std::formatter<::dice::template_library::variant2> { template constexpr auto parse(Ctx &ctx) { @@ -922,5 +922,3 @@ struct std::formatter<::dice::template_library::variant2> { }, var); } }; - -#endif // DICE_TEMPLATELIBRARY_VARIANT2_HPP diff --git a/src/dice/template-library/version.cppm b/src/dice/template-library/version.cppm new file mode 100644 index 0000000..364a54e --- /dev/null +++ b/src/dice/template-library/version.cppm @@ -0,0 +1,10 @@ +module; +#include +export module dice.template_library:version; + +export namespace dice::template_library { + inline constexpr char name[] = "dice-template-library"; + inline constexpr char version[] = "2.6.0"; + inline constexpr std::array version_tuple = {2, 6, 0}; + inline constexpr int pobr_version = 2; ///< persisted object binary representation version +} // namespace dice::template_library diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt index f77ff5a..3ede8da 100644 --- a/test_package/CMakeLists.txt +++ b/test_package/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.22) +cmake_minimum_required(VERSION 3.28) project(test_package) find_package(dice-template-library REQUIRED) diff --git a/test_package/test_package.cpp b/test_package/test_package.cpp index 2c0ad5e..3cb6eb4 100644 --- a/test_package/test_package.cpp +++ b/test_package/test_package.cpp @@ -1,4 +1,6 @@ -#include +#include + +import dice.template_library; int main() { int i = 7; @@ -6,5 +8,5 @@ int main() { i, [](auto i) -> int { return i * 2; }, []() -> int { return -1; }); if (res != 14) - exit(1); + std::exit(1); } \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c52c6c5..064f8b9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ macro(CUSTOM_ADD_TEST) FATAL_ERROR "Call to 'CUSTOM_ADD_TEST' with ${ARGC} arguments instead of 1") endif() + target_compile_features(${ARGV0} PUBLIC cxx_std_23) add_test(NAME ${ARGV0} COMMAND ${ARGV0}) target_link_libraries( ${ARGV0} PRIVATE doctest::doctest dice-template-library::dice-template-library) diff --git a/tests/tests_channel.cpp b/tests/tests_channel.cpp index f24ab00..c819fea 100644 --- a/tests/tests_channel.cpp +++ b/tests/tests_channel.cpp @@ -1,8 +1,6 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include @@ -10,6 +8,8 @@ #include #include +import dice.template_library; + TEST_SUITE("mpmc_channel") { using namespace dice::template_library; diff --git a/tests/tests_defer.cpp b/tests/tests_defer.cpp index b91e354..fdaa00d 100644 --- a/tests/tests_defer.cpp +++ b/tests/tests_defer.cpp @@ -82,4 +82,18 @@ namespace dice::template_library { DICE_DEFER_TO_SUCCESS {}; } } + + TEST_CASE("move if value") { + int value = 0; + int &ref = value; + int const &cref = value; + int &&rref = std::move(value); + int const &&crref = std::move(value); + + static_assert(std::is_same_v); // move + static_assert(std::is_same_v); // no move + static_assert(std::is_same_v); // no move + static_assert(std::is_same_v); // move + static_assert(std::is_same_v); // no move + } } // namespace dice::template_library diff --git a/tests/tests_flex_array.cpp b/tests/tests_flex_array.cpp index b15ad16..2024009 100644 --- a/tests/tests_flex_array.cpp +++ b/tests/tests_flex_array.cpp @@ -1,8 +1,6 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include @@ -11,6 +9,8 @@ #include #include +import dice.template_library; + namespace dice::template_library { // extern templates sometimes make problems if internal types are too eagerly instantiated extern template struct flex_array; diff --git a/tests/tests_fmt_join.cpp b/tests/tests_fmt_join.cpp index ee445ec..ecd4c69 100644 --- a/tests/tests_fmt_join.cpp +++ b/tests/tests_fmt_join.cpp @@ -1,7 +1,5 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include @@ -10,6 +8,8 @@ #include #include +import dice.template_library; + namespace dtl = dice::template_library; TEST_SUITE("join formatter") { diff --git a/tests/tests_for.cpp b/tests/tests_for.cpp index f161234..018f8e6 100644 --- a/tests/tests_for.cpp +++ b/tests/tests_for.cpp @@ -1,12 +1,11 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include #include +import dice.template_library; namespace dice::template_library { TEST_SUITE("testing of compile time for_types") { diff --git a/tests/tests_format_to_ostream.cpp b/tests/tests_format_to_ostream.cpp index bbf41d8..5b96b81 100644 --- a/tests/tests_format_to_ostream.cpp +++ b/tests/tests_format_to_ostream.cpp @@ -1,7 +1,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include +import dice.template_library; struct definitely_not_ostreamable { int x; diff --git a/tests/tests_functional.cpp b/tests/tests_functional.cpp index e55ee12..c4b3c23 100644 --- a/tests/tests_functional.cpp +++ b/tests/tests_functional.cpp @@ -1,10 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include +import dice.template_library; + double func(int x, double d) { return x + d; } diff --git a/tests/tests_inplace_polymorphic.cpp b/tests/tests_inplace_polymorphic.cpp index c59d16d..46c9598 100644 --- a/tests/tests_inplace_polymorphic.cpp +++ b/tests/tests_inplace_polymorphic.cpp @@ -1,12 +1,12 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - +#include #include #include #include -#include + +import dice.template_library; namespace dtl = dice::template_library; diff --git a/tests/tests_integral_template_tuple.cpp b/tests/tests_integral_template_tuple.cpp index 9a27538..c83c6a6 100644 --- a/tests/tests_integral_template_tuple.cpp +++ b/tests/tests_integral_template_tuple.cpp @@ -1,12 +1,12 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include #include +import dice.template_library; + namespace dice::template_library { template diff --git a/tests/tests_integral_template_variant.cpp b/tests/tests_integral_template_variant.cpp index 16544f0..3b8098f 100644 --- a/tests/tests_integral_template_variant.cpp +++ b/tests/tests_integral_template_variant.cpp @@ -1,11 +1,11 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include +import dice.template_library; + namespace dice::template_library { template diff --git a/tests/tests_lazy_conditional.cpp b/tests/tests_lazy_conditional.cpp index 11baa95..95951ed 100644 --- a/tests/tests_lazy_conditional.cpp +++ b/tests/tests_lazy_conditional.cpp @@ -1,11 +1,11 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include +import dice.template_library; + namespace dice::template_library { TEST_SUITE("lazy_conditional") { template diff --git a/tests/tests_limit_allocator.cpp b/tests/tests_limit_allocator.cpp index e52dc58..d2fed42 100644 --- a/tests/tests_limit_allocator.cpp +++ b/tests/tests_limit_allocator.cpp @@ -1,7 +1,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include +import dice.template_library; TEST_SUITE("limit_allocator sanity check") { using namespace dice::template_library; diff --git a/tests/tests_mutex.cpp b/tests/tests_mutex.cpp index 013883d..4d117f7 100644 --- a/tests/tests_mutex.cpp +++ b/tests/tests_mutex.cpp @@ -1,9 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include #include +import dice.template_library; + TEST_SUITE("mutex") { using namespace dice::template_library; diff --git a/tests/tests_next_to_range.cpp b/tests/tests_next_to_range.cpp index 032585e..cace0f3 100644 --- a/tests/tests_next_to_range.cpp +++ b/tests/tests_next_to_range.cpp @@ -1,14 +1,13 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - - #include #include #include #include +import dice.template_library; + namespace dtl = dice::template_library; TEST_SUITE("next_to_range") { @@ -183,7 +182,7 @@ TEST_SUITE("next_to_range") { CHECK_EQ(ints[2], 2); CHECK_EQ(ints[3], 3); - std::ranges::equal(ints, std::vector{0, 1, 2, 3}); + CHECK(std::ranges::equal(ints, std::vector{0, 1, 2, 3})); ints.advance(0); CHECK(std::ranges::equal(ints, std::vector{0, 1, 2, 3})); diff --git a/tests/tests_opt_minmax.cpp b/tests/tests_opt_minmax.cpp index 3383bfa..8688e9b 100644 --- a/tests/tests_opt_minmax.cpp +++ b/tests/tests_opt_minmax.cpp @@ -1,11 +1,11 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include #include +import dice.template_library; + namespace dice::template_library { TEST_SUITE("opt_minmax") { TEST_CASE("opt_min") { diff --git a/tests/tests_overloaded.cpp b/tests/tests_overloaded.cpp index ec3e6f3..34072c7 100644 --- a/tests/tests_overloaded.cpp +++ b/tests/tests_overloaded.cpp @@ -1,10 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include +import dice.template_library; + TEST_SUITE("overloaded") { TEST_CASE("variant") { std::variant v{std::in_place_type, 5}; diff --git a/tests/tests_pointer_tag_pair.cpp b/tests/tests_pointer_tag_pair.cpp index a3c14cb..5262b03 100644 --- a/tests/tests_pointer_tag_pair.cpp +++ b/tests/tests_pointer_tag_pair.cpp @@ -1,7 +1,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include +import dice.template_library; TEST_SUITE("pointer_tag_pair") { using namespace dice::template_library; diff --git a/tests/tests_polymorphic_allocator.cpp b/tests/tests_polymorphic_allocator.cpp index 6afa380..a4e705a 100644 --- a/tests/tests_polymorphic_allocator.cpp +++ b/tests/tests_polymorphic_allocator.cpp @@ -1,12 +1,12 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include +import dice.template_library; + template struct mallocator { using value_type = T; diff --git a/tests/tests_pool_allocator.cpp b/tests/tests_pool_allocator.cpp index 792fb6c..161ef97 100644 --- a/tests/tests_pool_allocator.cpp +++ b/tests/tests_pool_allocator.cpp @@ -1,12 +1,17 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include +#include + +#include +#include + +import dice.template_library; + TEST_SUITE("pool allocator") { TEST_CASE("basic pool functions work") { dice::template_library::pool pool; diff --git a/tests/tests_ranges.cpp b/tests/tests_ranges.cpp index bf2207d..53e3317 100644 --- a/tests/tests_ranges.cpp +++ b/tests/tests_ranges.cpp @@ -1,8 +1,6 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include @@ -13,6 +11,8 @@ #include #include +import dice.template_library; + namespace dtl = dice::template_library; TEST_SUITE("range adaptors for all_of, any_of, none_of") { diff --git a/tests/tests_shared_mutex.cpp b/tests/tests_shared_mutex.cpp index 3638795..242628a 100644 --- a/tests/tests_shared_mutex.cpp +++ b/tests/tests_shared_mutex.cpp @@ -1,9 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include #include +import dice.template_library; + TEST_SUITE("shared_mutex") { using namespace dice::template_library; diff --git a/tests/tests_standard_layout_tuple.cpp b/tests/tests_standard_layout_tuple.cpp index 215cc4e..cdf5387 100644 --- a/tests/tests_standard_layout_tuple.cpp +++ b/tests/tests_standard_layout_tuple.cpp @@ -3,8 +3,7 @@ #include -#include -#include +import dice.template_library; TEST_SUITE("standard layout tuple") { using namespace dice::template_library; diff --git a/tests/tests_static_string.cpp b/tests/tests_static_string.cpp index 4619292..6a7897c 100644 --- a/tests/tests_static_string.cpp +++ b/tests/tests_static_string.cpp @@ -1,10 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include +import dice.template_library; + TEST_SUITE("static_string") { using namespace dice::template_library; @@ -37,7 +37,7 @@ TEST_SUITE("static_string") { template void check_non_empty_string(basic_static_string, Allocator> const &actual, std::string_view expected) { - assert(!expected.empty()); + REQUIRE(!expected.empty()); REQUIRE_EQ(actual.size(), expected.size()); REQUIRE_EQ(actual, actual); diff --git a/tests/tests_stdint.cpp b/tests/tests_stdint.cpp index 411a4ad..619afa8 100644 --- a/tests/tests_stdint.cpp +++ b/tests/tests_stdint.cpp @@ -1,12 +1,12 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include +import dice.template_library.literals; + TEST_SUITE("stdint") { using namespace dice::template_library::literals; diff --git a/tests/tests_switch_cases.cpp b/tests/tests_switch_cases.cpp index 5970360..4678ad9 100644 --- a/tests/tests_switch_cases.cpp +++ b/tests/tests_switch_cases.cpp @@ -1,9 +1,9 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - #include +import dice.template_library; + namespace dice::template_library { TEST_SUITE("testing of the compiled switch") { const int value = 1; diff --git a/tests/tests_tuple_algorithm.cpp b/tests/tests_tuple_algorithm.cpp index 930a5a9..57b87f5 100644 --- a/tests/tests_tuple_algorithm.cpp +++ b/tests/tests_tuple_algorithm.cpp @@ -1,7 +1,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include +import dice.template_library; namespace dice::template_library { diff --git a/tests/tests_type_list.cpp b/tests/tests_type_list.cpp index 0942084..965c19d 100644 --- a/tests/tests_type_list.cpp +++ b/tests/tests_type_list.cpp @@ -1,8 +1,6 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include #include #include @@ -13,6 +11,8 @@ #include #include +import dice.template_library; + TEST_SUITE("type_list") { namespace tl = dice::template_library::type_list; using empty_t = tl::type_list<>; diff --git a/tests/tests_type_traits.cpp b/tests/tests_type_traits.cpp index 3d03660..37dbc7f 100644 --- a/tests/tests_type_traits.cpp +++ b/tests/tests_type_traits.cpp @@ -1,9 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include #include +import dice.template_library; + TEST_SUITE("type_traits") { using namespace dice::template_library; @@ -96,18 +97,4 @@ TEST_SUITE("type_traits") { static_assert(std::is_same_v().get()), int &&>); static_assert(std::is_same_v().get()), int const &&>); } - - TEST_CASE("move if value") { - int value = 0; - int &ref = value; - int const &cref = value; - int &&rref = std::move(value); - int const &&crref = std::move(value); - - static_assert(std::is_same_v); // move - static_assert(std::is_same_v); // no move - static_assert(std::is_same_v); // no move - static_assert(std::is_same_v); // move - static_assert(std::is_same_v); // no move - } } diff --git a/tests/tests_variant2.cpp b/tests/tests_variant2.cpp index d478768..b3e37d6 100644 --- a/tests/tests_variant2.cpp +++ b/tests/tests_variant2.cpp @@ -1,9 +1,10 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include -#include - #include +#include + +import dice.template_library; using namespace std::string_literals;