1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/*
* File: option.hpp
* Author: Amlal El Mahrouss,
* Copyright 2023-2025, Amlal El Mahrouss, Licensed under the Boost Software License
*/
#ifndef __OCL_CORE_OPTION
#define __OCL_CORE_OPTION
#include <ocl/detail/config.hpp>
#include <utility>
namespace ocl
{
enum struct return_type
{
invalid = 0,
okay = 100,
err,
count = err - okay + 1,
};
class option final
{
public:
option() = delete;
explicit option(const return_type& return_type)
: ret_(return_type)
{
assert(ret_ != return_type::invalid);
}
~option() = default;
option& operator=(const option&) = delete;
option(const option&) = delete;
option& expect(const char* input)
{
assert(ret_ != return_type::invalid);
if (ret_ == return_type::err)
{
throw std::runtime_error(input ? input : "option::error");
}
return *this;
}
template <typename ErrorHandler>
option& expect_or_handle(const char* input)
{
assert(ret_ != return_type::invalid);
if (ret_ == return_type::err)
{
// AMLALE: Shall it be a functor or container here?
ErrorHandler{}(input ? input : "option::error");
}
return *this;
}
private:
return_type ret_{return_type::invalid};
};
namespace detail
{
// AMLALE: They (operator()) were marked `noexcept` as failing conditions within an evaluation (say a overloads operator==) proves that the
// predictate is wrong.
struct teller
{
explicit teller() = default;
virtual ~teller() = default;
template <class ObjFirst, class ObjLast>
bool operator()(ObjFirst a, ObjLast b) noexcept
{
return false;
}
};
struct int_eq_teller final : teller
{
template <class ObjFirst, class ObjLast>
bool operator()(ObjFirst a, ObjLast b) noexcept
{
return (a == b);
}
};
struct int_greater_than_teller final : teller
{
template <class ObjFirst, class ObjLast>
bool operator()(ObjFirst a, ObjLast b) noexcept
{
return (a > b);
}
};
struct int_less_than_teller final : teller
{
template <class ObjFirst, class ObjLast>
bool operator()(ObjFirst a, ObjLast b) noexcept
{
return (a < b);
}
};
} // namespace detail
template <typename Teller, typename... Lst>
inline return_type eval(const Teller& tell, Lst&&... arg)
{
static_assert(std::is_base_of_v<detail::teller, Teller>, "Teller is not evalueable.");
return tell(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err;
}
template <typename... Lst>
inline return_type eval_less_than(Lst&&... arg) noexcept
{
return detail::int_less_than_teller{}(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err;
}
template <typename... Lst>
inline return_type eval_eq(Lst&&... arg) noexcept
{
return detail::int_eq_teller{}(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err;
}
template <typename... Lst>
inline return_type eval_greater_than(Lst&&... arg) noexcept
{
return detail::int_greater_than_teller{}(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err;
}
inline return_type eval_true() noexcept
{
return return_type::okay;
}
inline return_type eval_false() noexcept
{
return return_type::err;
}
inline return_type eval_invalid() noexcept
{
return return_type::invalid;
}
} // namespace ocl
#endif /* ifndef __OCL_CORE_OPTION */
|