Sequoia
Loading...
Searching...
No Matches
Advice.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2020. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
24
25namespace sequoia::testing
26{
28 template<class Advisor>
30
31 template<class R, class Advisor, class T>
32 struct advisor_invoke_type<R (Advisor::*)(T, T)>
33 {
34 using return_type = R;
35 using type = T;
36 };
37
38 template<class R, class Advisor, class T>
39 struct advisor_invoke_type<R (Advisor::*)(T, T) const>
40 {
41 using return_type = R;
42 using type = T;
43 };
44
45 template<class R, class Advisor, class T>
46 struct advisor_invoke_type<R (Advisor::*)(T, T) const noexcept>
47 {
48 using return_type = R;
49 using type = T;
50 };
51
52 template<class R, class Advisor, class T>
53 struct advisor_invoke_type<R (Advisor::*)(T, T) noexcept>
54 {
55 using return_type = R;
56 using type = T;
57 };
58
60 template<class Advisor, class T>
62 {
63 constexpr static bool utilize{false};
64 };
65
66 template<class Advisor, class T>
67 requires std::invocable<Advisor, T, T>
68 struct advisor_analyser<Advisor, T>
69 {
70 constexpr static bool utilize{true};
71 };
72
73 // Attempt to disallow bindings which involve a narrowing conversion. I can only think
74 // how to do this in the case of a single operator(), hence this specialization.
75 // The logic to prohibit narrowing occurs in the definition of `utilize`.
76 template<class Advisor, class T>
77 requires std::invocable<Advisor, T, T> && requires {
78 std::declval<decltype(&Advisor::operator())>();
79 }
80 struct advisor_analyser<Advisor, T>
81 {
82 private:
83 using type = std::remove_cvref_t<typename advisor_invoke_type<decltype(&Advisor::operator())>::type>;
84 public:
85 constexpr static bool utilize{std::is_same_v<std::common_type_t<type, std::remove_cvref_t<T>>, type>};
86 };
87
88 template<class Advisor, class T>
89 inline constexpr bool use_advisor_v{advisor_analyser<Advisor, T>::utilize};
90
93 {};
94
125 template<class Advisor>
126 class tutor
127 {
128 public:
129 using sequoia_advisor_type = Advisor;
130
131 tutor(Advisor a, std::string prefix="Advice: ")
132 : m_Advisor{std::move(a)}
133 , m_Prefix{std::move(prefix)}
134 {}
135
136 template<class T>
137 requires use_advisor_v<Advisor, T>
138 [[nodiscard]]
139 std::string operator()(const T& value, const T& prediction) const
140 {
141 return m_Advisor(value, prediction);
142 }
143
144 [[nodiscard]]
145 const std::string& prefix() const noexcept
146 {
147 return m_Prefix;
148 }
149 private:
150 Advisor m_Advisor;
151 std::string m_Prefix;
152 };
153
154 template<>
156 {
157 public:
159 };
160
161 template<class Tutor>
162 inline constexpr bool is_teacher_v{
163 requires { typename std::remove_cvref_t<Tutor>::sequoia_advisor_type; }
164 };
165
166 template<class... U>
167 struct ends_with_tutor : std::false_type
168 {};
169
170 template<class... U>
171 requires (sizeof...(U) > 0u)
172 && is_teacher_v<decltype(std::get<sizeof...(U) - 1>(std::declval<std::tuple<std::remove_cvref_t<U>&...>>()))>
173 struct ends_with_tutor<U...> : std::true_type
174 {};
175
176
177 template<class... U>
178 inline constexpr bool ends_with_tutor_v{ends_with_tutor<U...>::value};
179
182 {
183 public:
184 template<class Advisor, class T>
185 advice_data(const tutor<Advisor>&, const T&, const T&)
186 {}
187
188 template<class Advisor, class T>
189 requires std::is_invocable_r_v<std::string, tutor<Advisor>, T, T>
190 advice_data(const tutor<Advisor>& advisor, const T& value, const T& prediction)
191 {
192 m_Advice = advisor(value, prediction);
193 m_Prefix = advisor.prefix();
194 }
195
196 std::string& append_to(std::string& message) const;
197 private:
198 std::string m_Advice{}, m_Prefix{};
199 };
200
201 std::string& append_advice(std::string& message, const advice_data& adviceData);
202}
Concepts which are sufficiently general to appear in the sequoia namespace.
A collection of functions for formatting test output.
Traits which are sufficiently general to appear in the sequoia namespace.
Helper for generating advice strings.
Definition: Advice.hpp:182
class template used to wrap function objects which proffer advice.
Definition: Advice.hpp:127
meta utility for determining whether a particular Advisor should be used for a given type
Definition: Advice.hpp:62
meta utility for garnering invocation and return types from an Advisor
Definition: Advice.hpp:29
Definition: Advice.hpp:168
Represents the absence of advice.
Definition: Advice.hpp:93