@@ -243,14 +243,27 @@ using apply_t = decltype(apply_v<T, range>);
243
243
244
244
```cpp
245
245
/**
246
- * Invokes function with compile-time info based on run-time info
246
+ * Invokes function with compile-time info based on meta- info
247
247
*
248
248
* @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>));
251
252
* @endcode
252
253
*/
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) {
254
267
```
255
268
256
269
```cpp
@@ -268,6 +281,15 @@ template<concepts::range auto range>
268
281
constexpr auto for_each(auto&& fn);
269
282
```
270
283
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
+
271
293
---
272
294
273
295
### FAQ
@@ -446,6 +468,7 @@ template<class T> struct meta {
446
468
static constexpr auto id = mp::info{gen()};
447
469
constexpr auto friend get(info<id>) { return meta{}; }
448
470
};
471
+ void failed();
449
472
} // namespace detail
450
473
451
474
/**
@@ -514,12 +537,13 @@ using apply_t = decltype(
514
537
* Invokes function with compile-time info based on run-time info
515
538
*
516
539
* @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>));
519
543
* @endcode
520
544
*/
521
545
template<class Fn, class T = decltype([]{})>
522
- constexpr auto invoke(Fn&& fn, info meta) {
546
+ [[nodiscard]] constexpr auto invoke(Fn&& fn, info meta) {
523
547
constexpr auto dispatch = [&]<size_t... Ns>(utility::index_sequence<Ns...>) {
524
548
return array{
525
549
[]<info N> {
@@ -535,15 +559,15 @@ constexpr auto invoke(Fn&& fn, info meta) {
535
559
}
536
560
537
561
/**
538
- * Invokes meta-function
562
+ * Invokes type_trait with meta-info
539
563
*
540
564
* @code
541
565
* static_assert(not invoke<std::is_const>(meta<int>));
542
566
* static_assert(invoke<std::is_const>(meta<const int>));
543
567
* @endcode
544
568
*/
545
569
template<template<class...> class T, class... Ts, auto = []{}>
546
- constexpr auto invoke(info meta) {
570
+ [[nodiscard]] constexpr auto invoke(info meta) {
547
571
return invoke([]<info meta> {
548
572
using type = type_of<meta>;
549
573
if constexpr (requires { T<type, Ts...>::value; }) {
@@ -570,6 +594,25 @@ constexpr auto for_each(auto&& fn) {
570
594
(fn.template operator()<range[Ns]>(), ...);
571
595
}(utility::make_index_sequence<range.size()>{});
572
596
}
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
+ }
573
616
} // namespace mp
574
617
575
618
#ifndef NTEST
@@ -580,11 +623,11 @@ namespace mp::test {
580
623
template<class T> struct is_const { static constexpr auto value = false; };
581
624
template<class T> struct is_const<const T> { static constexpr auto value = true; };
582
625
template<class T> struct add_const { using type = const T; };
583
- void failed(); constexpr void expect(bool cond) { if (not cond) { failed(); } }
584
626
} // namespace mp::test
585
627
586
628
static_assert(([] {
587
629
using namespace mp::test;
630
+ using mp::expect;
588
631
589
632
// mp::test
590
633
{
@@ -609,8 +652,8 @@ static_assert(([] {
609
652
// mp::array
610
653
{
611
654
{
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());
614
657
}
615
658
616
659
{
0 commit comments