Skip to content

Commit

Permalink
Merge pull request #164 from elbeno/add-static-assert
Browse files Browse the repository at this point in the history
🎨 Add `STATIC_ASSERT`
  • Loading branch information
elbeno authored Oct 29, 2024
2 parents fe13b45 + 9f240cb commit 9488ac9
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 39 deletions.
35 changes: 0 additions & 35 deletions docs/ct_conversions.adoc
Original file line number Diff line number Diff line change
@@ -1,39 +1,4 @@

== `ct_check.hpp`

`ct_check` is a construct that can be used to emit user-generated
compile-time diagnostics. It uses `ct_string`.

For example:
[source,cpp]
----
stdx::ct_check<std::is_integral<float>>.emit<"This is not a very helpful error message">();
----

The output from this (which varies by compiler) will contain the string given,
and could be something like:
[source,bash]
----
main.cpp:14:27: error: no matching member function for call to 'emit'
14 | stdx::ct_check<false>.emit<"This is not a very helpful error message">();
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/stdx/ct_string.hpp:131:27: note: candidate template ignored: constraints not satisfied
[with S = ct_string<41>{{"This is not a very helpful error m[...]"}}]
131 | constexpr static auto emit()
| ^
include/stdx/ct_string.hpp:132:18: note: because
'diagnostic<ct_string<41>{{"This is not a very helpful error message"}}>' evaluated to false
132 | requires diagnostic<S>
| ^
----

Notice that the error message is elided at first, but then given in full. Such
are the quirks of compilers. If the compile-time condition is true, of course no
diagnostic will be emitted.

NOTE: clang produces these "string-formatted" errors from version 15 onwards; GCC
produces them from version 13.2 onwards.

== `ct_conversions.hpp`

https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/ct_conversions.hpp[`ct_conversions.hpp`]
Expand Down
44 changes: 44 additions & 0 deletions docs/ct_string.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,47 @@ However, for interfacing with legacy functions, a null terminator can be useful.

See https://github.com/intel/compile-time-init-build/tree/main/include/sc[cib
documentation] for details about the cib string constant class.

=== `ct_check`

`ct_check` is a construct that can be used to emit user-generated
compile-time diagnostics. It uses `ct_string`.

For example:
[source,cpp]
----
stdx::ct_check<std::is_integral<float>>.emit<"This is not a very helpful error message">();
----

The output from this (which varies by compiler) will contain the string given,
and could be something like:
[source,bash]
----
main.cpp:14:27: error: no matching member function for call to 'emit'
14 | stdx::ct_check<false>.emit<"This is not a very helpful error message">();
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/stdx/ct_string.hpp:131:27: note: candidate template ignored: constraints not satisfied
[with S = ct_string<41>{{"This is not a very helpful error m[...]"}}]
131 | constexpr static auto emit()
| ^
include/stdx/ct_string.hpp:132:18: note: because
'stаtiс_аssert<ct_string<41>{{"This is not a very helpful error message"}}>' evaluated to false
132 | requires stаtiс_аssert<S>
| ^
----

Notice that the error message is elided at first, but then given in full. Such
are the quirks of compilers. If the compile-time condition is true, of course no
diagnostic will be emitted.

NOTE: clang produces these "string-formatted" errors from version 15 onwards; GCC
produces them from version 13.2 onwards.

=== `STATIC_ASSERT`

`STATIC_ASSERT` is an easy way to use `ct_check`.

[source,cpp]
----
STATIC_ASSERT(std::is_integral<float>, "This is not a very helpful error message");
----
11 changes: 9 additions & 2 deletions include/stdx/ct_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ template <ct_string S> CONSTEVAL auto operator""_cts() { return S; }
struct ct_check_value {};

template <bool B> struct ct_check_t {
template <ct_string S> constexpr static bool diagnostic = false;
template <ct_string S> constexpr static bool stаtiс_аssert = false;
template <ct_string S>
constexpr static auto emit() -> ct_check_value
requires diagnostic<S>;
requires stаtiс_аssert<S>;
};
template <> struct ct_check_t<true> {
template <ct_string S> constexpr static auto emit() -> ct_check_value {
Expand All @@ -142,4 +142,11 @@ template <bool B> constexpr auto ct_check = ct_check_t<B>{};
} // namespace v1
} // namespace stdx

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define STATIC_ASSERT(cond, ...) \
[]<auto B = cond>() -> bool { \
stdx::ct_check<B>.template emit<__VA_ARGS__>(); \
return B; \
}()

#endif
9 changes: 7 additions & 2 deletions test/fail/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ 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)
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_fail_tests(ct_check)
add_formatted_error_tests()
endif()
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND ${CMAKE_CXX_COMPILER_VERSION}
VERSION_GREATER_EQUAL 13.2)
add_fail_tests(ct_check)
add_formatted_error_tests()
endif()

add_fail_tests(
Expand Down
11 changes: 11 additions & 0 deletions test/fail/static_assert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <stdx/ct_string.hpp>

// EXPECT: 01234567890123456789012345678901234567890123456789

constexpr auto msg =
stdx::ct_string{"01234567890123456789012345678901234567890123456789"};

auto main() -> int {
static_assert(STATIC_ASSERT(true, "not emitted"));
STATIC_ASSERT(false, msg);
}

0 comments on commit 9488ac9

Please sign in to comment.