diff --git a/.github/workflows/bvt-appleclang.yml b/.github/workflows/bvt-appleclang.yml index cc1f0504..7e9d8381 100644 --- a/.github/workflows/bvt-appleclang.yml +++ b/.github/workflows/bvt-appleclang.yml @@ -20,7 +20,7 @@ jobs: - name: build and run test with AppleClang run: | - cmake -B build -DCMAKE_BUILD_TYPE=Release + cmake -B build -DCMAKE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Release cmake --build build -j ctest --test-dir build -j diff --git a/.github/workflows/bvt-clang.yml b/.github/workflows/bvt-clang.yml index c58b1004..d8d765d4 100644 --- a/.github/workflows/bvt-clang.yml +++ b/.github/workflows/bvt-clang.yml @@ -15,39 +15,25 @@ jobs: - name: install clang run: | - sudo apt install -y clang-16 clang-17 clang-18 libc++-18-dev + sudo apt install -y clang-19 libc++-19-dev - - name: check compiler versions + - name: check compiler version run: | - clang++-16 --version - clang++-17 --version - clang++-18 --version + clang++-19 --version - - name: build and run test with clang 16 + - name: build and run test with clang 19 run: | - cmake -B build-clang-16 -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release - cmake --build build-clang-16 -j - ctest --test-dir build-clang-16 -j - - - name: build and run test with clang 17 - run: | - cmake -B build-clang-17 -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release - cmake --build build-clang-17 -j - ctest --test-dir build-clang-17 -j - - - name: build and run test with clang 18 - run: | - cmake -B build-clang-18 -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release - cmake --build build-clang-18 -j - ctest --test-dir build-clang-18 -j + cmake -B build -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Release + cmake --build build -j + ctest --test-dir build -j - name: run benchmarks run: | - cd build-clang-18/benchmarks + cd build/benchmarks ./msft_proxy_benchmarks --benchmark_min_warmup_time=0.1 --benchmark_min_time=0.1s --benchmark_repetitions=30 --benchmark_enable_random_interleaving=true --benchmark_report_aggregates_only=true --benchmark_format=json > benchmarking-results.json - name: archive benchmarking results uses: actions/upload-artifact@v4 with: name: benchmarking-results-clang - path: build-clang-18/benchmarks/benchmarking-results.json + path: build/benchmarks/benchmarking-results.json diff --git a/.github/workflows/bvt-compatibility.yml b/.github/workflows/bvt-compatibility.yml new file mode 100644 index 00000000..4169e634 --- /dev/null +++ b/.github/workflows/bvt-compatibility.yml @@ -0,0 +1,64 @@ +on: + workflow_call: + inputs: + branch: + type: string + required: false + +jobs: + bvt-compatibility: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + + - name: install compilers + run: | + sudo apt install -y gcc-13 g++-13 gcc-14 g++-14 clang-16 clang-17 clang-18 clang-19 libc++-19-dev + + - name: check compiler versions + run: | + g++-13 --version + g++-14 --version + clang++-16 --version + clang++-17 --version + clang++-18 --version + clang++-19 --version + + - name: build and run test with gcc 13 + run: | + cmake -B build-gcc-13 -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 -DCMAKE_BUILD_TYPE=Release + cmake --build build-gcc-13 -j + ctest --test-dir build-gcc-13 -j + + - name: build and run test with gcc 14 + run: | + cmake -B build-gcc-14 -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_BUILD_TYPE=Release + cmake --build build-gcc-14 -j + ctest --test-dir build-gcc-14 -j + + # Note that libc++ in Clang 19 is not compatible with Clang 16. Therefore, we fallback to libstdc++. + - name: build and run test with clang 16 + run: | + cmake -B build-clang-16 -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_BUILD_TYPE=Release + cmake --build build-clang-16 -j + ctest --test-dir build-clang-16 -j + + - name: build and run test with clang 17 + run: | + cmake -B build-clang-17 -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release + cmake --build build-clang-17 -j + ctest --test-dir build-clang-17 -j + + - name: build and run test with clang 18 + run: | + cmake -B build-clang-18 -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release + cmake --build build-clang-18 -j + ctest --test-dir build-clang-18 -j + + - name: build and run test with clang 19 + run: | + cmake -B build-clang-19 -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release + cmake --build build-clang-19 -j + ctest --test-dir build-clang-19 -j diff --git a/.github/workflows/bvt-gcc.yml b/.github/workflows/bvt-gcc.yml index ea33f230..e3a86037 100644 --- a/.github/workflows/bvt-gcc.yml +++ b/.github/workflows/bvt-gcc.yml @@ -15,32 +15,25 @@ jobs: - name: install gcc run: | - sudo apt install -y gcc-13 g++-13 gcc-14 g++-14 + sudo apt install -y gcc-14 g++-14 - - name: check compiler versions + - name: check compiler version run: | - g++-13 --version g++-14 --version - - name: build and run test with gcc 13 - run: | - cmake -B build-gcc-13 -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13 -DCMAKE_BUILD_TYPE=Release - cmake --build build-gcc-13 -j - ctest --test-dir build-gcc-13 -j - - name: build and run test with gcc 14 run: | - cmake -B build-gcc-14 -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_BUILD_TYPE=Release - cmake --build build-gcc-14 -j - ctest --test-dir build-gcc-14 -j + cmake -B build -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Release + cmake --build build -j + ctest --test-dir build -j - name: run benchmarks run: | - cd build-gcc-14/benchmarks + cd build/benchmarks ./msft_proxy_benchmarks --benchmark_min_warmup_time=0.1 --benchmark_min_time=0.1s --benchmark_repetitions=30 --benchmark_enable_random_interleaving=true --benchmark_report_aggregates_only=true --benchmark_format=json > benchmarking-results.json - name: archive benchmarking results uses: actions/upload-artifact@v4 with: name: benchmarking-results-gcc - path: build-gcc-14/benchmarks/benchmarking-results.json + path: build/benchmarks/benchmarking-results.json diff --git a/.github/workflows/bvt-msvc.yml b/.github/workflows/bvt-msvc.yml index 0f5aecbb..eff391be 100644 --- a/.github/workflows/bvt-msvc.yml +++ b/.github/workflows/bvt-msvc.yml @@ -7,7 +7,7 @@ on: jobs: bvt-msvc: - runs-on: windows-2022 + runs-on: windows-2025 steps: - uses: actions/checkout@v4 with: @@ -15,7 +15,7 @@ jobs: - name: build and run test with MSVC run: | - cmake -B build + cmake -B build -DCMAKE_CXX_STANDARD=23 cmake --build build --config Release -j ctest --test-dir build -j diff --git a/.github/workflows/bvt-nvhpc.yml b/.github/workflows/bvt-nvhpc.yml index 4dcc808e..273428f7 100644 --- a/.github/workflows/bvt-nvhpc.yml +++ b/.github/workflows/bvt-nvhpc.yml @@ -23,17 +23,17 @@ jobs: - name: build and run test with NVHPC 24.9 run: | PATH=/opt/nvidia/hpc_sdk/Linux_x86_64/24.9/compilers/bin:$PATH; export PATH - cmake -B build-nv -DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++ -DCMAKE_BUILD_TYPE=Release - cmake --build build-nv -j - ctest --test-dir build-nv -j + cmake -B build -DCMAKE_C_COMPILER=nvc -DCMAKE_CXX_COMPILER=nvc++ -DCMAKE_BUILD_TYPE=Release + cmake --build build -j + ctest --test-dir build -j - name: run benchmarks run: | - cd build-nv/benchmarks + cd build/benchmarks ./msft_proxy_benchmarks --benchmark_min_warmup_time=0.1 --benchmark_min_time=0.1s --benchmark_repetitions=30 --benchmark_enable_random_interleaving=true --benchmark_report_aggregates_only=true --benchmark_format=json > benchmarking-results.json - name: archive benchmarking results uses: actions/upload-artifact@v4 with: name: benchmarking-results-nvhpc - path: build-nv/benchmarks/benchmarking-results.json + path: build/benchmarks/benchmarking-results.json diff --git a/.github/workflows/pipeline-ci.yml b/.github/workflows/pipeline-ci.yml index 9cc56653..28b0dcbd 100644 --- a/.github/workflows/pipeline-ci.yml +++ b/.github/workflows/pipeline-ci.yml @@ -28,6 +28,10 @@ jobs: uses: ./.github/workflows/bvt-nvhpc.yml name: Run BVT with NVHPC + run-bvt-compatibility: + uses: ./.github/workflows/bvt-compatibility.yml + name: Run BVT for compatibility + report: uses: ./.github/workflows/bvt-report.yml name: Generate report diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 3b500d1f..393f5cd9 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -26,6 +26,8 @@ target_link_libraries(msft_proxy_benchmarks PRIVATE msft_proxy benchmark::benchm if (MSVC) target_compile_options(msft_proxy_benchmarks PRIVATE /W4) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(msft_proxy_benchmarks PRIVATE -Wall -Wextra -Wpedantic -Wno-c++2b-extensions) else() target_compile_options(msft_proxy_benchmarks PRIVATE -Wall -Wextra -Wpedantic) endif() diff --git a/proxy.h b/proxy.h index 74877c92..3a6882f2 100644 --- a/proxy.h +++ b/proxy.h @@ -22,10 +22,10 @@ #include #endif // __STDC_HOSTED__ -#ifdef __cpp_rtti +#if __cpp_rtti >= 199711L #include #include -#endif // __cpp_rtti +#endif // __cpp_rtti >= 199711L #if __has_cpp_attribute(msvc::no_unique_address) #define ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE msvc::no_unique_address @@ -35,11 +35,11 @@ #error "Proxy requires C++20 attribute no_unique_address" #endif -#ifdef __cpp_exceptions +#if __cpp_exceptions >= 199711L #define ___PRO_THROW(...) throw __VA_ARGS__ #else #define ___PRO_THROW(...) std::abort() -#endif // __cpp_exceptions +#endif // __cpp_exceptions >= 199711L #ifdef _MSC_VER #define ___PRO_ENFORCE_EBO __declspec(empty_bases) @@ -1576,12 +1576,18 @@ constexpr proxy make_proxy_shared(T&& value) } #endif // __STDC_HOSTED__ -#ifdef __cpp_rtti +#if __cpp_rtti >= 199711L class bad_proxy_cast : public std::bad_cast { public: char const* what() const noexcept override { return "pro::bad_proxy_cast"; } }; -#endif // __cpp_rtti +#endif // __cpp_rtti >= 199711L + +#if __cpp_static_call_operator >= 202207L +#define ___PRO_STATIC_CALL(__R, ...) static __R operator()(__VA_ARGS__) +#else +#define ___PRO_STATIC_CALL(__R, ...) __R operator()(__VA_ARGS__) const +#endif // __cpp_static_call_operator >= 202207L #define ___PRO_DIRECT_FUNC_IMPL(...) \ noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \ @@ -1672,7 +1678,7 @@ class bad_proxy_cast : public std::bad_cast { #define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - decltype(auto) operator()(__T&& __self, __Args&&... __args) const \ + ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ ___PRO_DIRECT_FUNC_IMPL(::std::forward<__T>(__self) \ .__FUNC(::std::forward<__Args>(__args)...)) \ ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \ @@ -1705,7 +1711,7 @@ ___PRO_DEBUG( \ #define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - decltype(auto) operator()(__T&& __self, __Args&&... __args) const \ + ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ ::std::forward<__Args>(__args)...)) \ ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_FREE_ACCESSOR, __FNAME) \ @@ -1720,7 +1726,7 @@ ___PRO_DEBUG( \ #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \ struct __NAME { \ template \ - decltype(auto) operator()(__T&& __self, __Args&&... __args) const \ + ___PRO_STATIC_CALL(decltype(auto), __T&& __self, __Args&&... __args) \ ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \ ::std::forward<__Args>(__args)...)) \ ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \ @@ -1758,7 +1764,7 @@ struct cast_dispatch_base { struct upward_conversion_dispatch : cast_dispatch_base { template - T&& operator()(T&& self) const noexcept { return std::forward(self); } + ___PRO_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } }; template @@ -1932,7 +1938,7 @@ using merge_facade_conv_t = typename add_upward_conversion_conv< struct proxy_view_dispatch : cast_dispatch_base { template - auto operator()(T& value) const noexcept + ___PRO_STATIC_CALL(auto, T& value) noexcept requires(requires { { std::addressof(*value) } noexcept; }) { return observer_ptr @@ -2026,7 +2032,7 @@ sign(const char (&str)[N]) -> sign; #if __STDC_HOSTED__ struct weak_conversion_dispatch : cast_dispatch_base { template - auto operator()(const P& self) const noexcept + ___PRO_STATIC_CALL(auto, const P& self) noexcept requires(requires { typename P::weak_type; } && std::is_convertible_v) { return typename P::weak_type{self}; } @@ -2078,14 +2084,14 @@ struct format_dispatch { // std::formatter by std::is_default_constructible_v as per // [format.formatter.spec]. template - OutIt operator()(const T& self, std::basic_string_view spec, - std::basic_format_context& fc) const + ___PRO_STATIC_CALL(OutIt, const T& self, std::basic_string_view spec, + std::basic_format_context& fc) requires( -#if defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L +#if __cpp_lib_format_ranges >= 202207L std::formattable #else std::is_default_constructible_v> -#endif // defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L +#endif // __cpp_lib_format_ranges >= 202207L ) { std::formatter impl; { @@ -2097,7 +2103,7 @@ struct format_dispatch { }; #endif // __STDC_HOSTED__ -#ifdef __cpp_rtti +#if __cpp_rtti >= 199711L struct proxy_cast_context { const std::type_info* type_ptr; bool is_ref; @@ -2152,7 +2158,7 @@ struct proxy_cast_accessor_impl { void(proxy_cast_context) Q> {} struct proxy_cast_dispatch { template - void operator()(T&& self, proxy_cast_context ctx) const { + ___PRO_STATIC_CALL(void, T&& self, proxy_cast_context ctx) { if (typeid(T) == *ctx.type_ptr) { if (ctx.is_ref) { if constexpr (std::is_lvalue_reference_v) { @@ -2199,18 +2205,18 @@ ___PRO_DEBUG( const std::type_info* info; }; -#endif // __cpp_rtti +#endif // __cpp_rtti >= 199711L struct wildcard { wildcard() = delete; template [[noreturn]] operator T() const { -#ifdef __cpp_lib_unreachable +#if __cpp_lib_unreachable >= 202202L std::unreachable(); #else std::abort(); -#endif // __cpp_lib_unreachable +#endif // __cpp_lib_unreachable >= 202202L } }; @@ -2264,7 +2270,7 @@ struct basic_facade_builder { using support_wformat = add_convention< details::format_dispatch, details::format_overload_t>; #endif // __STDC_HOSTED__ -#ifdef __cpp_rtti +#if __cpp_rtti >= 199711L using support_indirect_rtti = basic_facade_builder< details::add_conv_t>, C>; using support_rtti = support_indirect_rtti; -#endif // __cpp_rtti +#endif // __cpp_rtti >= 199711L using support_view = add_direct_convention>; using build = details::facade_impl; @@ -2340,18 +2346,18 @@ struct operator_dispatch; #define ___PRO_DEF_LHS_ALL_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR #define ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(...) \ template \ - decltype(auto) operator()(T&& self) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self) \ ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) #define ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL(...) \ template \ - decltype(auto) operator()(T&& self) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self) \ ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward(self)) \ template \ - decltype(auto) operator()(T&& self, int) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self, int) \ ___PRO_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__) #define ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(...) \ template \ - decltype(auto) operator()(T&& self, Arg&& arg) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ ___PRO_DIRECT_FUNC_IMPL( \ std::forward(self) __VA_ARGS__ std::forward(arg)) #define ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL(...) \ @@ -2386,7 +2392,7 @@ ___PRO_DEBUG( \ template <> \ struct operator_dispatch<#__VA_ARGS__, true> { \ template \ - decltype(auto) operator()(T&& self, Arg&& arg) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ ___PRO_DIRECT_FUNC_IMPL( \ std::forward(arg) __VA_ARGS__ std::forward(self)) \ ___PRO_DEF_FREE_ACCESSOR_TEMPLATE( \ @@ -2433,7 +2439,7 @@ ___PRO_DEBUG( \ template <> \ struct operator_dispatch<#__VA_ARGS__, false> { \ template \ - decltype(auto) operator()(T&& self, Arg&& arg) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ ___PRO_DIRECT_FUNC_IMPL(std::forward(self) __VA_ARGS__ \ std::forward(arg)) \ ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR, \ @@ -2442,7 +2448,7 @@ ___PRO_DEBUG( \ template <> \ struct operator_dispatch<#__VA_ARGS__, true> { \ template \ - decltype(auto) operator()(T&& self, Arg&& arg) const \ + ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) \ ___PRO_DIRECT_FUNC_IMPL( \ std::forward(arg) __VA_ARGS__ std::forward(self)) \ ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR, \ @@ -2487,23 +2493,23 @@ ___PRO_BINARY_OP_DISPATCH_IMPL(->*) template <> struct operator_dispatch<"()", false> { template - decltype(auto) operator()(T&& self, Args&&... args) const + ___PRO_STATIC_CALL(decltype(auto), T&& self, Args&&... args) ___PRO_DIRECT_FUNC_IMPL( std::forward(self)(std::forward(args)...)) ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator()) }; template <> struct operator_dispatch<"[]", false> { -#if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L +#if __cpp_multidimensional_subscript >= 202110L template - decltype(auto) operator()(T&& self, Args&&... args) const + ___PRO_STATIC_CALL(decltype(auto), T&& self, Args&&... args) ___PRO_DIRECT_FUNC_IMPL( std::forward(self)[std::forward(args)...]) #else template - decltype(auto) operator()(T&& self, Arg&& arg) const + ___PRO_STATIC_CALL(decltype(auto), T&& self, Arg&& arg) ___PRO_DIRECT_FUNC_IMPL(std::forward(self)[std::forward(arg)]) -#endif // defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L +#endif // __cpp_multidimensional_subscript >= 202110L ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator[]) }; @@ -2528,11 +2534,11 @@ struct operator_dispatch<"[]", false> { struct implicit_conversion_dispatch : details::cast_dispatch_base { template - T&& operator()(T&& self) const noexcept { return std::forward(self); } + ___PRO_STATIC_CALL(T&&, T&& self) noexcept { return std::forward(self); } }; struct explicit_conversion_dispatch : details::cast_dispatch_base { template - auto operator()(T&& self) const noexcept + ___PRO_STATIC_CALL(auto, T&& self) noexcept { return details::explicit_conversion_adapter{std::forward(self)}; } }; using conversion_dispatch = explicit_conversion_dispatch; @@ -2546,7 +2552,7 @@ template struct weak_dispatch : D { using D::operator(); template - [[noreturn]] details::wildcard operator()(std::nullptr_t, Args&&...) const + [[noreturn]] ___PRO_STATIC_CALL(details::wildcard, std::nullptr_t, Args&&...) { ___PRO_THROW(not_implemented{}); } }; @@ -2555,7 +2561,7 @@ struct weak_dispatch : D { "Use pro::weak_dispatch<" #__D "> instead.")]] __NAME : __D { \ using __D::operator(); \ template \ - decltype(auto) operator()(::std::nullptr_t, __Args&&... __args) const \ + ___PRO_STATIC_CALL(decltype(auto), ::std::nullptr_t, __Args&&... __args) \ ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__Args>(__args)...)) \ } diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 46b53b33..29deb3ea 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -10,10 +10,11 @@ foreach(SOURCE ${SOURCES}) set(FULL_EXECUTABLE_NAME "${DIR_UNDERSCORE}_${EXECUTABLE_NAME}") add_executable(${FULL_EXECUTABLE_NAME} ${SOURCE}) target_link_libraries(${FULL_EXECUTABLE_NAME} PRIVATE msft_proxy) + if (MSVC) + target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE /W4) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic -Wno-c++2b-extensions) + else() + target_compile_options(${FULL_EXECUTABLE_NAME} PRIVATE -Wall -Wextra -Wpedantic) + endif() endforeach() - -if (MSVC) - add_compile_options(/W4) -else() - add_compile_options(-Wall -Wextra -Wpedantic) -endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d5070c9f..020c48b8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,6 +35,8 @@ target_link_libraries(msft_proxy_tests PRIVATE gtest_main) if(MSVC) target_compile_options(msft_proxy_tests PRIVATE /W4 /WX) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(msft_proxy_tests PRIVATE -Wall -Wextra -Wpedantic -Wno-c++2b-extensions -Werror) else() target_compile_options(msft_proxy_tests PRIVATE -Wall -Wextra -Wpedantic -Werror) endif() @@ -46,7 +48,11 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang add_executable(msft_proxy_freestanding_tests freestanding/proxy_freestanding_tests.cpp) target_include_directories(msft_proxy_freestanding_tests PRIVATE .) target_compile_features(msft_proxy_freestanding_tests PRIVATE cxx_std_20) - target_compile_options(msft_proxy_freestanding_tests PRIVATE -ffreestanding -fno-exceptions -fno-rtti -Wall -Wextra -Wpedantic -Werror) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(msft_proxy_freestanding_tests PRIVATE -ffreestanding -fno-exceptions -fno-rtti -Wall -Wextra -Wpedantic -Wno-c++2b-extensions -Werror) + else() + target_compile_options(msft_proxy_freestanding_tests PRIVATE -ffreestanding -fno-exceptions -fno-rtti -Wall -Wextra -Wpedantic -Werror) + endif() target_link_options(msft_proxy_freestanding_tests PRIVATE -nodefaultlibs -lc) target_link_libraries(msft_proxy_freestanding_tests PRIVATE msft_proxy) add_test(NAME ProxyFreestandingTests COMMAND msft_proxy_freestanding_tests) diff --git a/tests/proxy_dispatch_tests.cpp b/tests/proxy_dispatch_tests.cpp index 090d2a69..aa08a6d0 100644 --- a/tests/proxy_dispatch_tests.cpp +++ b/tests/proxy_dispatch_tests.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include +#include #include #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -12,6 +13,10 @@ #pragma warning(pop) #endif // defined(_MSC_VER) && !defined(__clang__) +#if __cpp_lib_mdspan >= 202207L +#include +#endif // __cpp_lib_mdspan >= 202207L + namespace proxy_dispatch_tests_details { struct CommaTester { @@ -333,7 +338,7 @@ TEST(ProxyDispatchTests, TestOpParentheses) { ASSERT_EQ((*p)(2, 3), 5); } -TEST(ProxyDispatchTests, TestOpBrackets) { +TEST(ProxyDispatchTests, TestOpBrackets_OneDimensional) { struct TestFacade : pro::facade_builder::add_convention, int&(int idx)>::build {}; std::unordered_map v; pro::proxy p = &v; @@ -342,6 +347,19 @@ TEST(ProxyDispatchTests, TestOpBrackets) { ASSERT_EQ(v.at(3), 12); } +#if __cpp_lib_mdspan >= 202207L +TEST(ProxyDispatchTests, TestOpBrackets_Multidimensional) { + struct TestFacade : pro::facade_builder::add_convention, int&(int i, int j, int k)>::build {}; + std::vector v(12, 1); + auto view = std::mdspan(v.data(), 2, 2, 3); + pro::proxy p = &view; + (*p)[1, 1, 1] = 123; + for (std::size_t i = 0u; i < v.size(); ++i) { + ASSERT_EQ(v[i], i == 10 ? 123 : 1); + } +} +#endif // __cpp_lib_mdspan >= 202207L + TEST(ProxyDispatchTests, TestRhsOpPlus) { struct TestFacade : pro::facade_builder::add_convention, int(int val)>::build {}; int v = 12;