diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index fd38ac1..250197d 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -7,10 +7,8 @@ on: branches: [ "master" ] jobs: - build: - + test-gcc-clang: runs-on: ubuntu-latest - steps: - name: Install just run: | @@ -32,3 +30,14 @@ jobs: - name: Build and Run Test with Clang 14 run: | just t clang++-14 + + test-msvc: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: ilammy/msvc-dev-cmd@v1 + with: + vsversion: 2022 + - name: Build and run Test with MSVC + run: | + nmake /f nmakefile diff --git a/include/conststr.hpp b/include/conststr.hpp index ca74fab..d081173 100644 --- a/include/conststr.hpp +++ b/include/conststr.hpp @@ -1194,9 +1194,7 @@ struct cstr { constexpr auto insert(const_iterator iter, const value_type &ch) const noexcept -> cstr { - iter = std::max(iter, cbegin()); - size_type pos = iter - cbegin(); - if (pos > N) pos = N; + size_type pos = to_pos(iter); if constexpr (Count == 0) return *this; else { @@ -1241,10 +1239,7 @@ struct cstr { */ template Str> constexpr auto insert(const_iterator iter, const Str &str) const noexcept { - iter = std::max(iter, cbegin()); - size_type pos = iter - cbegin(); - if (pos > N) pos = N; - + size_type pos = to_pos(iter); auto other = conststr::cstr(str); constexpr size_type N2 = decltype(other)::size(); cstr ret{}; @@ -1370,10 +1365,7 @@ struct cstr { constexpr auto replace(const_iterator first, const_iterator last, const value_type &ch) const noexcept -> cstr { - first = std::max(first, cbegin()); - last = std::min(last, cend()); - size_type pos = first - cbegin(); - size_type count = last - first; + auto [pos, count] = to_pos_len(first, last); cstr ret = *this; size_type end = std::min(pos + count, N); for (size_type i = pos; i < end; ++i) ret[i] = ch; @@ -1413,10 +1405,7 @@ struct cstr { constexpr auto replace(const_iterator first, const_iterator last, const view_type &str) const noexcept -> cstr { - first = std::max(first, cbegin()); - last = std::min(last, cend()); - size_type pos = first - cbegin(); - size_type count = last - first; + auto [pos, count] = to_pos_len(first, last); return replace(pos, str, count); } @@ -1498,9 +1487,7 @@ struct cstr { */ constexpr auto erase(const_iterator iter) const noexcept -> cstr { - iter = std::max(iter, cbegin()); - size_type pos = iter - cbegin(); - if (pos >= N) return pop(); + size_type pos = to_pos(iter); cstr ret{}; for (size_type i = 0; i < pos; ++i) ret[i] = _str[i]; for (size_type i = pos; i < N - 1; ++i) ret[i] = _str[i + 1]; @@ -1661,8 +1648,7 @@ struct cstr { constexpr size_type find(const value_type &ch, size_type pos = 0) const noexcept { if (pos >= npos) return npos; - auto iter = std::find(cbegin() + pos, cend(), ch); - return iter - cbegin(); + return to_pos(std::find(cbegin() + pos, cend(), ch)); } /** @@ -1674,9 +1660,8 @@ struct cstr { constexpr size_type find(const view_type &str, size_type pos = 0) const noexcept { if (pos >= npos) return npos; - auto iter = - std::search(cbegin() + pos, cend(), str.cbegin(), str.cend()); - return iter - cbegin(); + return to_pos( + std::search(cbegin() + pos, cend(), str.cbegin(), str.cend())); } /** @@ -1690,7 +1675,7 @@ struct cstr { auto beg = pos >= npos ? crbegin() : const_reverse_iterator(cbegin() + pos); auto iter = std::find(beg, crend(), ch); - return iter.base() - cbegin() - 1; + return iter == crend() ? npos : to_pos(iter.base() - 1); } /** @@ -1704,7 +1689,7 @@ struct cstr { auto beg = pos >= npos ? crbegin() : const_reverse_iterator(cbegin() + pos); auto iter = std::search(beg, crend(), str.crbegin(), str.crend()); - return iter.base() - cbegin() - str.size(); + return iter == crend() ? npos : to_pos(iter.base() - str.size()); } /** @@ -1718,8 +1703,7 @@ struct cstr { constexpr size_type find_if(UnaryPredicate p, size_type pos = 0) const noexcept { if (pos >= npos) return npos; - auto iter = std::find_if(cbegin() + pos, cend(), p); - return iter - cbegin(); + return to_pos(std::find_if(cbegin() + pos, cend(), p)); } /** @@ -1735,7 +1719,7 @@ struct cstr { auto beg = pos >= npos ? crbegin() : const_reverse_iterator(begin() + pos); auto iter = std::find_if(beg, crend(), p); - return iter.base() - cbegin() - 1; + return iter == crend() ? npos : to_pos(iter.base() - 1); } /** @@ -1824,6 +1808,18 @@ struct cstr { * you should not access it directly. Instead, you should use `begin()` and `end()`. */ value_type _str[N + 1]; + + private: + inline constexpr size_t to_pos(const_iterator iter) const noexcept { + return std::min(size_t(std::max(iter, cbegin()) - cbegin()), N); + } + + inline constexpr std::tuple to_pos_len( + const_iterator first, const_iterator last) const noexcept { + size_t first_pos = to_pos(first); + size_t last_pos = to_pos(last); + return {first_pos, std::max(first_pos, last_pos) - first_pos}; + } }; /** diff --git a/include/reflect.hpp b/include/reflect.hpp index fda66d8..7b5b1f4 100644 --- a/include/reflect.hpp +++ b/include/reflect.hpp @@ -1727,7 +1727,7 @@ constexpr decltype(auto) to_tuple(T &&t) */ template struct cptr { - const T *const ptr; + const T *ptr; }; #if defined(__clang__) diff --git a/justfile b/justfile index ae2e68a..0007cd2 100644 --- a/justfile +++ b/justfile @@ -3,9 +3,12 @@ outpath := "./build" include := "./include" default_cc := "/usr/bin/env g++" cppflags := "-std=c++20 -Wall" +set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] alias b := build-tests alias t := run-tests +alias nt := nmake-tests +alias c := clean build-tests cc=default_cc: #!/bin/bash @@ -25,3 +28,10 @@ run-tests cc=default_cc: (build-tests cc) for bin in {{ outpath }}/*; do $bin; done + +nmake-tests: + nmake -f nmakefile + Get-ChildItem build -Filter *.exe | Foreach-Object { & $_.FullName } + +clean: + rm -r ./build diff --git a/nmakefile b/nmakefile new file mode 100755 index 0000000..c5c1d1f --- /dev/null +++ b/nmakefile @@ -0,0 +1,17 @@ + +CC = cl +INCLUDES = ./include +CXXFLAGS = /std:c++20 /EHs /Wall /Fo./build/ + +EXES = $(**:.cpp=.exe) + +.SUFFIXES: .cpp .exe +all: tests\*.cpp + mkdir build + $(MAKE) /f nmakefile $(EXES:tests=build) + +{tests\}.cpp{build\}.exe: + $(CC) /I $(INCLUDES) $(CXXFLAGS) /Fe$@ $< + +clean: + del /Q build diff --git a/tests/test-conststr.cpp b/tests/test-conststr.cpp index c2e3ee1..5e082e8 100644 --- a/tests/test-conststr.cpp +++ b/tests/test-conststr.cpp @@ -119,4 +119,4 @@ int main() { std::cout << __FILE__ ": all tests passed." << std::endl; return 0; -} \ No newline at end of file +} diff --git a/tests/test-reflect.cpp b/tests/test-reflect.cpp index 441bcc7..5628717 100644 --- a/tests/test-reflect.cpp +++ b/tests/test-reflect.cpp @@ -56,4 +56,4 @@ int main() { std::cout << __FILE__ ": all tests passed." << std::endl; return 0; -} \ No newline at end of file +}