Skip to content

✨ Add reason to = delete where available #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion include/stdx/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,26 @@
#endif

#define STDX_DO_PRAGMA(X) _Pragma(#X)
#ifdef __clang__
#if defined(__clang__)
#define STDX_PRAGMA(X) STDX_DO_PRAGMA(clang X)
#else
#define STDX_PRAGMA(X) STDX_DO_PRAGMA(GCC X)
#endif

#ifndef STDX_DELETED
#if __cpp_deleted_function >= 202403L
#if defined(__clang__)
#define STDX_DELETED(R) \
STDX_PRAGMA(diagnostic push) \
STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option") \
STDX_PRAGMA(diagnostic ignored "-Wc++26-extensions") = \
delete (R)STDX_PRAGMA(diagnostic pop)
#else
#define STDX_DELETED(R) = delete (R)
#endif
#else
#define STDX_DELETED(R) = delete
#endif
#endif

// NOLINTEND(cppcoreguidelines-macro-usage)
25 changes: 21 additions & 4 deletions include/stdx/rollover.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <stdx/compiler.hpp>
#include <stdx/concepts.hpp>

#include <type_traits>
Expand Down Expand Up @@ -77,10 +78,26 @@ template <typename T> struct rollover_t {
return not(lhs == rhs);
}

friend constexpr auto operator<(rollover_t, rollover_t) -> bool = delete;
friend constexpr auto operator<=(rollover_t, rollover_t) -> bool = delete;
friend constexpr auto operator>(rollover_t, rollover_t) -> bool = delete;
friend constexpr auto operator>=(rollover_t, rollover_t) -> bool = delete;
friend constexpr auto operator<(rollover_t, rollover_t)
-> bool STDX_DELETED(
"Comparison operators on rollover_t are deleted because "
"they are non-transitive. If you know your data is safe, "
"you can use cmp_less(rollover_t, rollover_t).");
friend constexpr auto operator<=(rollover_t, rollover_t)
-> bool STDX_DELETED(
"Comparison operators on rollover_t are deleted because "
"they are non-transitive. If you know your data is safe, "
"you can use cmp_less(rollover_t, rollover_t).");
friend constexpr auto operator>(rollover_t, rollover_t)
-> bool STDX_DELETED(
"Comparison operators on rollover_t are deleted because "
"they are non-transitive. If you know your data is safe, "
"you can use cmp_less(rollover_t, rollover_t).");
friend constexpr auto operator>=(rollover_t, rollover_t)
-> bool STDX_DELETED(
"Comparison operators on rollover_t are deleted because "
"they are non-transitive. If you know your data is safe, "
"you can use cmp_less(rollover_t, rollover_t).");

[[nodiscard]] friend constexpr auto cmp_less(rollover_t lhs, rollover_t rhs)
-> bool {
Expand Down
58 changes: 29 additions & 29 deletions test/fail/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,7 @@ add_fail_tests(
template_for_each_not_list
to_address_undefined_on_function)

function(add_formatted_error_tests)
add_fail_tests(ct_check)
add_fail_tests(static_assert)
add_fail_tests(static_assert_format)
endfunction()

function(add_26_formatted_error_tests)
add_compile_fail_test("static_assert.cpp" NAME static_assert_26 LIBRARIES
stdx)
add_compile_fail_test("static_assert_format.cpp" NAME
static_assert_format_26 LIBRARIES stdx)
target_compile_features(EXPECT_FAIL.static_assert_26 PRIVATE cxx_std_26)
target_compile_features(EXPECT_FAIL.static_assert_format_26
PRIVATE cxx_std_26)
endfunction()

if(${CMAKE_CXX_STANDARD} GREATER_EQUAL 20)
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"
AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL 15)
add_formatted_error_tests()
endif()
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND ${CMAKE_CXX_COMPILER_VERSION}
VERSION_GREATER_EQUAL 13.2)
add_formatted_error_tests()
endif()

if("cxx_std_26" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
add_26_formatted_error_tests()
endif()

add_fail_tests(
atomic_bool_dec
ct_format_mismatch
Expand All @@ -69,3 +40,32 @@ if(${CMAKE_CXX_STANDARD} GREATER_EQUAL 20)
tuple_spaceship_with_element
tuple_type_not_found)
endif()

function(add_test_by_compiler CPP_NAME CXX_VERSION COMPILER_ID COMPILER_VERSION)
if("cxx_std_${CXX_VERSION}" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "${COMPILER_ID}"
AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL
${COMPILER_VERSION})
set(TEST_NAME "${CPP_NAME}_${COMPILER_ID}_${COMPILER_VERSION}")
add_compile_fail_test("${CPP_NAME}.cpp" NAME ${TEST_NAME} LIBRARIES
stdx)
target_compile_features("EXPECT_FAIL.${TEST_NAME}"
PRIVATE "cxx_std_${CXX_VERSION}")
endif()
endif()
endfunction()

add_test_by_compiler(ct_check 20 Clang 15)
add_test_by_compiler(ct_check 20 GNU 13.2)
add_test_by_compiler(static_assert 20 Clang 15)
add_test_by_compiler(static_assert 20 GNU 13.2)
add_test_by_compiler(static_assert_format 20 Clang 15)
add_test_by_compiler(static_assert_format 20 GNU 13.2)

add_test_by_compiler(static_assert 26 Clang 17)
add_test_by_compiler(static_assert 26 GNU 14)
add_test_by_compiler(static_assert_format 26 Clang 17)
add_test_by_compiler(static_assert_format 26 GNU 14)

add_test_by_compiler(rollover_less_than_26 26 Clang 19)
add_test_by_compiler(rollover_less_than_26 26 GNU 15)
8 changes: 8 additions & 0 deletions test/fail/rollover_less_than_26.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stdx/rollover.hpp>

// EXPECT: deleted because they are non-transitive

auto main() -> int {
using X = stdx::rollover_t<unsigned int>;
[[maybe_unused]] auto cmp = X{} < X{1u};
}
Loading