diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml new file mode 100644 index 0000000..3f42598 --- /dev/null +++ b/.github/workflows/clang.yml @@ -0,0 +1,17 @@ +name: Clang + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + container: + image: medwellwillis/clang-gcc-cmake-vcpkg-git:0.2 + + steps: + - uses: actions/checkout@v2 + + - name: Build With Clang + run: | + cmake --preset clang-ninja + cmake --build ./build/clang-ninja --config Release \ No newline at end of file diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml new file mode 100644 index 0000000..55f9001 --- /dev/null +++ b/.github/workflows/emscripten.yml @@ -0,0 +1,22 @@ +name: Emscripten + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + container: + image: emscripten/emsdk + + steps: + - uses: actions/checkout@v2 + + - name: Get Ninja + run: | + python3 -m pip install ninja + + - name: Build With Emscripten + run: | + mkdir -p build/emscripten-ninja + emcmake cmake --preset emscripten-ninja -DCMAKE_SUPPRESS_DEVELOPER_WARNINGS=ON + cmake --build build/emscripten-ninja --config Release \ No newline at end of file diff --git a/.github/workflows/gcc.yml b/.github/workflows/gcc.yml new file mode 100644 index 0000000..9e417af --- /dev/null +++ b/.github/workflows/gcc.yml @@ -0,0 +1,22 @@ +name: GCC + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + container: + image: medwellwillis/clang-gcc-cmake-vcpkg-git:0.2 + + steps: + - uses: actions/checkout@v2 + + - name: Build With GCC + run: | + cmake --preset gcc-ninja + cmake --build ./build/gcc-ninja --config Release + + - name: Run Tests + run: | + ./build/gcc-ninja/UtilyTest + ./build/gcc-ninja/UtilyBenchmark \ No newline at end of file diff --git a/.github/workflows/native-build.yml b/.github/workflows/native-build.yml deleted file mode 100644 index da75053..0000000 --- a/.github/workflows/native-build.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: C++ CI - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - container: - image: ardupilot/ardupilot-dev-clang:latest - - steps: - - uses: actions/checkout@v2 - - - name: Build Clang - run: | - cmake --preset clang-ninja - cmake --build build/clang-ninja - - - name: Build GCC - run: | - cmake --preset gcc-ninja - cmake --build build/gcc-ninja diff --git a/CMakeLists.txt b/CMakeLists.txt index 85537fb..4cc9199 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,10 +20,7 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy DESTINATION ${CMAKE_CURRENT_BI if(DEFINED EMSCRIPTEN) message(STATUS "For Emscripten SIMD use flags: \"-msimd128 -mrelaxed-simd -msse -msse2 -mavx\"") elseif(NOT MSVC) - # Enable all the warnings. target_compile_options(Utily_Utily PRIVATE "-Wall" "-Wextra" "-Wpedantic" "-Wcast-align" "-Wcast-qual" "-Wctor-dtor-privacy" "-Wformat=2" "-Winit-self" "-Wmissing-declarations" "-Wmissing-include-dirs" "-Wold-style-cast" "-Woverloaded-virtual" "-Wredundant-decls" "-Wshadow" "-Wsign-conversion" "-Wsign-promo" "-Wstrict-overflow=5" "-Wswitch-default" "-Wundef" "-Wno-unused" "-Wconversion" "-Wsign-compare") - # For std::format. - # target_compile_options(Utily_Utily PRIVATE -fexperimental-library) message(STATUS "For Native SIMD use flags: \"-mavx2 -mavx512bw\"") endif() @@ -74,12 +71,15 @@ if(BUILD_UTILY_BENCHMARKS) find_package(benchmark CONFIG) if(NOT benchmark_FOUND) message(STATUS "Downloading Benchmark...") + FetchContent_Declare( benchmark GIT_REPOSITORY https://github.com/google/benchmark GIT_TAG main GIT_SHALLOW FALSE ) + + set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Disable Google Benchmark tests" FORCE) FetchContent_MakeAvailable(benchmark) endif() add_executable(UtilyBenchmark ${UTILY_BENCHMARK_SOURCES}) diff --git a/CMakePresets.json b/CMakePresets.json index 39d614f..7f86a52 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -14,7 +14,11 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "BUILD_UTILY_TESTS": "ON", - "BUILD_UTILY_BENCHMARKS": "ON" + "BUILD_UTILY_BENCHMARKS": "ON", + "HAVE_STEADY_CLOCK": "0", + "HAVE_POSIX_REGEX": "0", + "HAVE_STD_REGEX": "0", + "HAVE_THREAD_SAFETY_ATTRIBUTES": "0" }, "environment": { "CC": "gcc", @@ -29,12 +33,35 @@ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "BUILD_UTILY_TESTS": "ON", - "BUILD_UTILY_BENCHMARKS": "ON" + "BUILD_UTILY_BENCHMARKS": "ON", + "HAVE_STEADY_CLOCK": "0", + "HAVE_POSIX_REGEX": "0", + "HAVE_STD_REGEX": "0", + "HAVE_THREAD_SAFETY_ATTRIBUTES": "0" }, "environment": { "CC": "clang", "CXX": "clang++" } + }, + { + "name": "emscripten-ninja", + "description": "Build with Emscripten SDK", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/emscripten-ninja", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_UTILY_TESTS": "ON", + "BUILD_UTILY_BENCHMARKS": "ON", + "HAVE_STEADY_CLOCK": "0", + "HAVE_POSIX_REGEX": "0", + "HAVE_STD_REGEX": "0", + "HAVE_THREAD_SAFETY_ATTRIBUTES": "0" + }, + "environment": { + "CC": "emcc", + "CXX": "em++" + } } ], "buildPresets": [ @@ -45,6 +72,10 @@ { "name": "clang-ninja", "configurePreset": "clang-ninja" + }, + { + "name": "emscripten-ninja", + "configurePreset": "emscripten-ninja" } ] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7e9fb52 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +# Start from Ubuntu base image +FROM ubuntu:latest + +RUN apt-get update +RUN apt-get upgrade -y +RUN apt-get install -y curl +RUN apt-get install -y git +RUN apt-get install -y unzip +RUN apt-get install -y tar +RUN apt-get install -y gcc g++ +RUN apt-get install -y wget +RUN apt-get install -y cmake +RUN apt-get install -y ninja-build +RUN apt-get install -y build-essential +RUN apt-get install -y clang=1:14.0-55~exp2 +RUN apt-get autoremove -y +RUN apt-get clean +RUN dpkg --configure -a +RUN apt-get install -y --no-install-recommends clang++=1:14.0-55~exp2 +RUN apt-get autoremove -y +RUN apt-get clean +RUN apt-get install -y zip +RUN git clone https://github.com/microsoft/vcpkg.git && ./vcpkg/bootstrap-vcpkg.sh -disableMetrics + +WORKDIR /workspace +COPY . . diff --git a/benchmark/BenchSimd.cpp b/benchmark/BenchSimd.cpp index 04adba1..eed5be2 100644 --- a/benchmark/BenchSimd.cpp +++ b/benchmark/BenchSimd.cpp @@ -2,25 +2,31 @@ // #define UTY_USE_SIMD_128 // #define UTY_USE_SIMD_256 // #define UTY_USE_SIMD_512 + #include "Utily/Utily.hpp" #include #include #include -#include #include +#include -constexpr static std::string_view LONG_STRING = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz"; -// constexpr static std::string_view LONG_STRING = "this is my testing zone"; +auto all_a(size_t max) -> std::string { + std::string v; + v.resize(max); + std::fill(v.begin(), v.end(), 'a'); + v.append("a"); + return v; +} +const static std::string LONG_STRING = all_a(10000); -auto iota(int32_t max) -> std::vector -{ +auto iota(size_t max) -> std::vector { std::vector v; v.resize(max); std::iota(v.begin(), v.end(), 0); + return v; } - const static std::vector NUMS = iota(10000); static void BM_Utily_Simd_find_char(benchmark::State& state) { diff --git a/benchmark/BenchSplit.cpp b/benchmark/BenchSplit.cpp index e4392f7..e1063dc 100644 --- a/benchmark/BenchSplit.cpp +++ b/benchmark/BenchSplit.cpp @@ -1,16 +1,18 @@ -#include #include "Utily/Utily.hpp" +#include #include #if 1 -constexpr static std::string_view LONG_STRING = "The quick brown fox jumps over the lazy dog while the energetic and spirited puppies, intrigued by the sudden burst of activity, start chasing their own tails, causing a delightful commotion in the serene and peaceful meadow that has, until now, been undisturbed by such playful endeavors"; + +// Apparently gcc's implementation of std::views::split is not compatible with const strings... +static std::string LONG_STRING = "The quick brown fox jumps over the lazy dog while the energetic and spirited puppies, intrigued by the sudden burst of activity, start chasing their own tails, causing a delightful commotion in the serene and peaceful meadow that has, until now, been undisturbed by such playful endeavors"; static void BM_Utily_SplitByElement(benchmark::State& state) { for (auto _ : state) { - for(auto word : Utily::split(LONG_STRING, ' ')) { - benchmark::DoNotOptimize(word); + for (auto word : Utily::split(LONG_STRING, ' ')) { + benchmark::DoNotOptimize(word); } } } @@ -18,8 +20,8 @@ BENCHMARK(BM_Utily_SplitByElement); static void BM_Utily_SplitByElements(benchmark::State& state) { for (auto _ : state) { - for(auto word : Utily::split(LONG_STRING, ' ', 't')) { - benchmark::DoNotOptimize(word); + for (auto word : Utily::split(LONG_STRING, ' ', 't')) { + benchmark::DoNotOptimize(word); } } } @@ -28,10 +30,9 @@ BENCHMARK(BM_Utily_SplitByElements); static void BM_Std_SplitByElement(benchmark::State& state) { for (auto _ : state) { auto splitter = LONG_STRING | std::views::split(' '); - for(auto word : splitter) { - benchmark::DoNotOptimize(word); + for (auto&& word : splitter) { + benchmark::DoNotOptimize(word); } - benchmark::DoNotOptimize(splitter); } } BENCHMARK(BM_Std_SplitByElement); diff --git a/build-all.bat b/build-all.bat index f3794c5..ec67c4a 100644 --- a/build-all.bat +++ b/build-all.bat @@ -10,17 +10,15 @@ call cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Release call cmake --build . --config Release cd .. - @REM WEB if not exist "build-web\" ( mkdir build-web ) cd build-web -call emcmake cmake .. -DCMAKE_TOOLCHAIN_FILE=%VCPKG_PATH%/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=wasm32-emscripten -DEMSCRIPTEN=1 -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=%EMSCRIPTEN%cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release +call emcmake cmake .. -DEMSCRIPTEN=1 -DCMAKE_BUILD_TYPE=Release call cmake --build . --config Release cd .. - cd build-native call UtilyTest.exe call UtilyBenchmark.exe \ No newline at end of file diff --git a/include/Utily/Concepts.hpp b/include/Utily/Concepts.hpp index 14b85bb..d42e12a 100644 --- a/include/Utily/Concepts.hpp +++ b/include/Utily/Concepts.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace Utily { namespace Concepts { @@ -44,7 +45,7 @@ namespace Utily { std::ranges::contiguous_range && std::ranges::sized_range && requires(T a) { { std::ranges::data(a) } -> std::contiguous_iterator; }; - + static_assert(IsContiguousRange); static_assert(!IsContiguousRange>); @@ -63,6 +64,11 @@ namespace Utily { t(param...) }; }; + + template + concept SubrangeCompatible = std::contiguous_iterator && requires(Iter a, Iter b) { + { std::ranges::subrange(a, b) } -> std::convertible_to>; + }; } } // namespace Utily diff --git a/include/Utily/InlineArrays.hpp b/include/Utily/InlineArrays.hpp index ea1e705..29792b6 100644 --- a/include/Utily/InlineArrays.hpp +++ b/include/Utily/InlineArrays.hpp @@ -18,7 +18,7 @@ namespace Utily { template static auto is_aligned(auto* ptr) { return reinterpret_cast(ptr) % alignof(T) == 0; - }; + } template requires(sizeof...(Size) == sizeof...(Types)) diff --git a/include/Utily/Simd.hpp b/include/Utily/Simd.hpp index 62a0d55..b848207 100644 --- a/include/Utily/Simd.hpp +++ b/include/Utily/Simd.hpp @@ -226,14 +226,14 @@ namespace Utily::Simd::Details { const size_t max_i_clamped = src_size - (src_size % chars_per_vec); - std::array<__m128i, max_values> vs; + __m128i vs[max_values]; for (size_t i = 0; i < value_size; ++i) { vs[i] = _mm_set1_epi8(value_begin[i]); } for (size_t i = 0; i < max_i_clamped; i += chars_per_vec) { const __m128i c = _mm_lddqu_si128(reinterpret_cast(src_begin + i)); - std::array<__m128i, max_values> eqs; + __m128i eqs[max_values]; for (size_t ii = 0; ii < value_size; ++ii) { eqs[ii] = _mm_cmpeq_epi8(c, vs[ii]); } @@ -251,7 +251,7 @@ namespace Utily::Simd::Details { memcpy(reinterpret_cast(&c), (src_begin + max_i_clamped), src_size - max_i_clamped); - std::array<__m128i, max_values> eqs; + __m128i eqs[max_values]; for (size_t i = 0; i < value_size; ++i) { eqs[i] = _mm_cmpeq_epi8(c, vs[i]); } diff --git a/include/Utily/Split.hpp b/include/Utily/Split.hpp index 27ca135..44ebe0e 100644 --- a/include/Utily/Split.hpp +++ b/include/Utily/Split.hpp @@ -1,11 +1,10 @@ #pragma once #include -#include #include #include #include -#include +#include #include #include #include @@ -15,8 +14,8 @@ #include #include -#include #include +#include namespace Utily { @@ -26,7 +25,7 @@ namespace Utily { requires std::equality_comparable_with> && (!std::is_reference_v) class ByElement { - using ContainerIter = typename Container::const_iterator; + using ContainerIter = decltype(std::ranges::cbegin(std::declval())); using ContainerValue = std::ranges::range_value_t; const Container& _container; @@ -39,6 +38,17 @@ namespace Utily { ByElement(Container&& container, const Delim& delim) = delete; + struct IterWrapper { + ContainerIter _begin; + ContainerIter _end; + auto begin() -> ContainerIter& { + return _begin; + } + auto end() -> ContainerIter& { + return _begin; + } + }; + struct Iterator { public: ContainerIter current_begin; @@ -69,12 +79,14 @@ namespace Utily { private: // purely for type deduction consteval static auto dereference_type() { - if constexpr (std::same_as) { + if constexpr (std::same_as && Utily::Concepts::IsContiguousRange) { return std::string_view {}; } else if constexpr (Utily::Concepts::IsContiguousRange) { return std::span {}; - } else { + } else if constexpr (Utily::Concepts::SubrangeCompatible) { return std::ranges::subrange {}; + } else { + return IterWrapper {}; } } using DereferenceType = std::decay_t; @@ -146,6 +158,17 @@ namespace Utily { : _container(container) , _delims(delims) { } + struct IterWrapper { + ContainerIter _begin; + ContainerIter _end; + auto begin() -> ContainerIter& { + return _begin; + } + auto end() -> ContainerIter& { + return _begin; + } + }; + struct Iterator { public: ContainerIter current_begin; @@ -174,16 +197,18 @@ namespace Utily { private: // purely for type deduction - consteval static auto deference_type() { - if constexpr (std::same_as) { + consteval static auto dereference_type() { + if constexpr (std::same_as && Utily::Concepts::IsContiguousRange) { return std::string_view {}; } else if constexpr (Utily::Concepts::IsContiguousRange) { return std::span {}; - } else { + } else if constexpr (Utily::Concepts::SubrangeCompatible) { return std::ranges::subrange {}; + } else { + return IterWrapper {}; } } - using DerefenceType = decltype(deference_type()); + using DerefenceType = decltype(dereference_type()); public: [[nodiscard]] constexpr auto operator*() const noexcept { diff --git a/include/Utily/StaticVector.hpp b/include/Utily/StaticVector.hpp index b46d3a9..4d6ba9b 100644 --- a/include/Utily/StaticVector.hpp +++ b/include/Utily/StaticVector.hpp @@ -39,7 +39,7 @@ namespace Utily { constexpr ~InternalT() { } }; - InternalT _data[S]; + InternalT _data[static_cast(S)]; std::ptrdiff_t _size; public: