Skip to content

Commit 4429a74

Browse files
committed
🔧 [expect]
1 parent 7d7021d commit 4429a74

File tree

1 file changed

+55
-12
lines changed

1 file changed

+55
-12
lines changed

mp

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,27 @@ using apply_t = decltype(apply_v<T, range>);
243243

244244
```cpp
245245
/**
246-
* Invokes function with compile-time info based on run-time info
246+
* Invokes function with compile-time info based on meta-info
247247
*
248248
* @code
249-
* info i = meta<conts int>; // run-time
250-
* static_assert(invoke([]<info m> { return std::is_const_v<type_of<m>>; }, i));
249+
* static_assert(invoke(
250+
* []<info m> { return std::is_const_v<type_of<m>>;
251+
* }, meta<conts int>));
251252
* @endcode
252253
*/
253-
constexpr auto invoke(auto&& fn, info meta);
254+
[[nodiscard]] constexpr auto invoke(auto&& fn, info meta);
255+
256+
```cpp
257+
/**
258+
* Invokes type_trait with meta-info
259+
*
260+
* @code
261+
* static_assert(not invoke<std::is_const>(meta<int>));
262+
* static_assert(invoke<std::is_const>(meta<const int>));
263+
* @endcode
264+
*/
265+
template<template<class...> class T, class... Ts>
266+
[[nodiscard]] constexpr auto invoke(info meta) {
254267
```
255268

256269
```cpp
@@ -268,6 +281,15 @@ template<concepts::range auto range>
268281
constexpr auto for_each(auto&& fn);
269282
```
270283

284+
``cpp
285+
/**
286+
* Asserts that condition is satisfied
287+
* - constant evaluation: calls undefined function `failed()`
288+
* - run-time evaluation: calls `breakpoint()`
289+
*/
290+
constexpr void expect(auto cond) requires requires { bool(cond); };
291+
```
292+
271293
---
272294

273295
### FAQ
@@ -446,6 +468,7 @@ template<class T> struct meta {
446468
static constexpr auto id = mp::info{gen()};
447469
constexpr auto friend get(info<id>) { return meta{}; }
448470
};
471+
void failed();
449472
} // namespace detail
450473

451474
/**
@@ -514,12 +537,13 @@ using apply_t = decltype(
514537
* Invokes function with compile-time info based on run-time info
515538
*
516539
* @code
517-
* info i = meta<conts int>; // run-time
518-
* static_assert(invoke([]<info m> { return std::is_const_v<type_of<m>>; }, i));
540+
* static_assert(invoke(
541+
* []<info m> { return std::is_const_v<type_of<m>>;
542+
* }, meta<conts int>));
519543
* @endcode
520544
*/
521545
template<class Fn, class T = decltype([]{})>
522-
constexpr auto invoke(Fn&& fn, info meta) {
546+
[[nodiscard]] constexpr auto invoke(Fn&& fn, info meta) {
523547
constexpr auto dispatch = [&]<size_t... Ns>(utility::index_sequence<Ns...>) {
524548
return array{
525549
[]<info N> {
@@ -535,15 +559,15 @@ constexpr auto invoke(Fn&& fn, info meta) {
535559
}
536560

537561
/**
538-
* Invokes meta-function
562+
* Invokes type_trait with meta-info
539563
*
540564
* @code
541565
* static_assert(not invoke<std::is_const>(meta<int>));
542566
* static_assert(invoke<std::is_const>(meta<const int>));
543567
* @endcode
544568
*/
545569
template<template<class...> class T, class... Ts, auto = []{}>
546-
constexpr auto invoke(info meta) {
570+
[[nodiscard]] constexpr auto invoke(info meta) {
547571
return invoke([]<info meta> {
548572
using type = type_of<meta>;
549573
if constexpr (requires { T<type, Ts...>::value; }) {
@@ -570,6 +594,25 @@ constexpr auto for_each(auto&& fn) {
570594
(fn.template operator()<range[Ns]>(), ...);
571595
}(utility::make_index_sequence<range.size()>{});
572596
}
597+
598+
/**
599+
* Asserts that condition is satisfied
600+
* - constant evaluation: calls undefined function `failed()`
601+
* - run-time evaluation: calls `breakpoint()`
602+
*/
603+
constexpr void expect(auto cond) requires requires { bool(cond); } {
604+
if (not cond) {
605+
if (__builtin_is_constant_evaluated()) {
606+
detail::failed();
607+
} else {
608+
#if defined (_MSC_VER)
609+
__debugbreak();
610+
#else
611+
__builtin_trap();
612+
#endif
613+
}
614+
}
615+
}
573616
} // namespace mp
574617

575618
#ifndef NTEST
@@ -580,11 +623,11 @@ namespace mp::test {
580623
template<class T> struct is_const { static constexpr auto value = false; };
581624
template<class T> struct is_const<const T> { static constexpr auto value = true; };
582625
template<class T> struct add_const { using type = const T; };
583-
void failed(); constexpr void expect(bool cond) { if (not cond) { failed(); } }
584626
} // namespace mp::test
585627

586628
static_assert(([] {
587629
using namespace mp::test;
630+
using mp::expect;
588631

589632
// mp::test
590633
{
@@ -609,8 +652,8 @@ static_assert(([] {
609652
// mp::array
610653
{
611654
{
612-
mp::array<mp::size_t, 1> a{};
613-
expect(1 == a.size());
655+
mp::array<mp::size_t, 1u> a{};
656+
expect(1u == a.size());
614657
}
615658

616659
{

0 commit comments

Comments
 (0)