Loading...
Searching...
No Matches
asserts.h
Go to the documentation of this file.
1
23
24#ifndef FCPP_VALIDATIONS_H
25#define FCPP_VALIDATIONS_H
26
27#include <exception>
28#include <optional>
29#include <sstream>
30#include <stdexcept>
31#include <string>
32#include <utility>
33
34namespace fcpp::asserts {
35
47class invariant {
48private:
49 // Only engaged when the condition is violated.
50 std::optional<std::ostringstream> message_;
51
52 explicit invariant(bool condition) {
53 if (!condition) {
54 message_.emplace();
55 }
56 }
57
58 // https://herbsutter.com/2014/05/03/reader-qa-how-can-i-prevent-a-type-from-being-instantiated-on-the-stack/
59 invariant() = delete;
60 invariant(const invariant &) = delete;
61 invariant &operator=(const invariant &) = delete;
62
63public:
64 ~invariant() noexcept(false) { // NOLINT(bugprone-exception-escape)
65 // Throwing while another exception unwinds the stack would terminate.
66 if (message_ && std::uncaught_exceptions() == 0) {
67 // Living dangerously, guaranteed not to live on the stack though. See
68 // above link.
69 throw std::invalid_argument(message_->str());
70 }
71 }
72
83 template <typename Text>
84 friend invariant &&operator<<(invariant &&item, const Text &text) {
85 if (item.message_) {
86 *item.message_ << text;
87 }
88 return std::move(item);
89 }
90
100 static invariant eval(bool condition) { return invariant(condition); }
101};
102
103} // namespace fcpp::asserts
104
105#endif // FCPP_VALIDATIONS_H
friend invariant && operator<<(invariant &&item, const Text &text)
Sets the message as an incoming stream.
Definition asserts.h:84
static invariant eval(bool condition)
Evaluate the invariant and throw std::invalid_argument if violated.
Definition asserts.h:100