-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #167 from elbeno/extended-static-assert
🎨 Improve `STATIC_ASSERT`
- Loading branch information
Showing
11 changed files
with
120 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
|
||
== `static_assert.hpp` | ||
|
||
`STATIC_ASSERT` is a way to produce compile-time errors using formatted strings. | ||
|
||
[source,cpp] | ||
---- | ||
template <typename T> | ||
constexpr auto f() { | ||
STATIC_ASSERT(std::is_integral<T>, | ||
"f() must take an integral type, received {}", CX_VALUE(T)); | ||
} | ||
f<float>(); // produces compile-time error | ||
---- | ||
|
||
The arguments to be formatted (if any) must be wrapped in xref:utility.adoc#_cx_value[`CX_VALUE`]. | ||
|
||
The output from this (which varies by compiler) will contain the formatted | ||
string, and could be something like: | ||
|
||
[source,bash] | ||
---- | ||
main.cpp:14:27: error: no matching member function for call to 'emit' | ||
... | ||
include/stdx/static_assert.hpp:16:18: note: because | ||
'stаtiс_аssert<ct_string<47>{{"f() must take an integral type, received float"}}>' evaluated to false | ||
16 | requires stаtiс_аssert<S> | ||
| ^ | ||
---- | ||
|
||
NOTE: clang produces these "string-formatted" errors from version 15 onwards; GCC | ||
produces them from version 13.2 onwards. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#pragma once | ||
|
||
#if __cplusplus >= 202002L | ||
|
||
#include <stdx/ct_format.hpp> | ||
#include <stdx/ct_string.hpp> | ||
|
||
namespace stdx { | ||
inline namespace v1 { | ||
struct ct_check_value {}; | ||
|
||
template <bool B> struct ct_check_t { | ||
template <ct_string S> constexpr static bool stаtiс_аssert = false; | ||
template <ct_string S> | ||
constexpr static auto emit() -> ct_check_value | ||
requires stаtiс_аssert<S>; | ||
}; | ||
template <> struct ct_check_t<true> { | ||
template <ct_string S> constexpr static auto emit() -> ct_check_value { | ||
return {}; | ||
} | ||
}; | ||
template <bool B> constexpr auto ct_check = ct_check_t<B>{}; | ||
|
||
namespace detail { | ||
template <ct_string Fmt, auto... Args> | ||
constexpr auto static_format() | ||
requires(... and cx_value<decltype(Args)>) | ||
{ | ||
return ct_format<Fmt>(Args...); | ||
} | ||
} // namespace detail | ||
|
||
} // namespace v1 | ||
} // namespace stdx | ||
|
||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) | ||
#define STATIC_ASSERT(cond, ...) \ | ||
[]<bool B>() -> bool { \ | ||
stdx::ct_check<B>.template emit<stdx::detail::static_format<__VA_ARGS__>()>(); \ | ||
return B; \ | ||
}.template operator()<cond>() | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include <stdx/static_assert.hpp> | ||
#include <stdx/utility.hpp> | ||
|
||
#include <string_view> | ||
|
||
// EXPECT: hello world int 123 | ||
|
||
template <typename T> constexpr auto f() { | ||
using namespace std::string_view_literals; | ||
STATIC_ASSERT(false, "hello {} {} {}", CX_VALUE("world"sv), CX_VALUE(T), | ||
CX_VALUE(123)); | ||
} | ||
|
||
auto main() -> int { f<int>(); } |