Skip to content

Commit d8f6f55

Browse files
committed
fix viability checking, return tristate instead of bool
1 parent f670710 commit d8f6f55

1 file changed

Lines changed: 46 additions & 37 deletions

File tree

include/chroma

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ consteval void panic(T const& message) {
2626
(void)is_complete_type(compile_error); // force instantiation
2727
}
2828

29-
constexpr struct unchecked_context {
29+
struct unchecked_context {
3030
template <typename F>
3131
static auto operator()(F&& f) {
3232
return [&]<typename... Ts>[[= unchecked_context{}]](Ts&&... args)
@@ -35,55 +35,62 @@ constexpr struct unchecked_context {
3535
#endif
3636
{ return std::forward<F>(f)(std::forward<Ts>(args)...); };
3737
}
38-
} unchecked;
38+
};
39+
40+
template <typename... Ts>
41+
struct assumed_colors {};
3942

40-
#ifdef __clang__
41-
consteval std::vector<std::meta::info> annotations_of_with_type(std::meta::info r,
42-
std::meta::info t) {
43-
return std::meta::annotations_of(r, t);
43+
consteval bool is_specialization(std::meta::info type, std::meta::info templ) {
44+
if (not is_type(type)) {
45+
throw "not a type";
46+
}
47+
return has_template_arguments(type) &&
48+
template_of(type) == (is_template(templ) ? templ : template_of(templ));
4449
}
45-
#else
46-
using std::meta::annotations_of_with_type;
47-
#endif
4850

49-
template <typename... Ts>
50-
struct AssumedColors {};
51+
enum struct Viability { accepted, rejected, ignored };
5152

52-
consteval bool is_viable(std::meta::info fnc, std::meta::info type) {
53-
if (fnc == std::meta::info()) {
54-
return true;
55-
}
53+
consteval Viability viability_of(std::meta::info fnc, std::meta::info type) {
54+
using enum Viability;
55+
if (fnc == std::meta::info()) {
56+
return ignored;
57+
}
5658

57-
auto is_convertible = [&](std::meta::info r) { return is_convertible_type(r, type); };
59+
auto is_convertible = [&](std::meta::info r) { return is_convertible_type(r, type); };
5860

59-
for (auto annotation : annotations_of(fnc) | std::views::transform(std::meta::type_of)) {
60-
if (annotation == ^^unchecked_context) {
61-
return true;
62-
}
63-
if (is_specialization(annotation, ^^AssumedColors) and
64-
std::ranges::any_of(template_arguments_of(annotation), is_convertible)) {
65-
return true;
66-
}
61+
for (auto annotation : annotations_of(fnc) | std::views::transform(std::meta::type_of)) {
62+
if (annotation == ^^unchecked_context) {
63+
return ignored;
64+
}
65+
if (is_specialization(annotation, ^^assumed_colors) and
66+
std::ranges::any_of(template_arguments_of(annotation), is_convertible)) {
67+
return accepted;
6768
}
69+
}
6870

69-
for (auto parameter : parameters_of(fnc) | std::views::transform(std::meta::type_of)) {
70-
if (is_specialization(parameter, template_of(^^callable_from)) and
71-
is_convertible(template_arguments_of(parameter)[0])) {
72-
return true;
73-
}
71+
for (auto parameter : parameters_of(fnc) | std::views::transform(std::meta::type_of)) {
72+
if (is_specialization(parameter, ^^callable_from) and
73+
is_convertible(template_arguments_of(parameter)[0])) {
74+
return accepted;
7475
}
75-
return false;
76+
}
77+
return rejected;
7678
}
7779
} // namespace _chroma_impl
7880

79-
using _chroma_impl::unchecked;
81+
constexpr _chroma_impl::unchecked_context unchecked{};
8082

8183
template <typename... Ts>
82-
constexpr _chroma_impl::AssumedColors<Ts...> assume_color{};
84+
constexpr _chroma_impl::assumed_colors<Ts...> assume_color{};
8385

8486
namespace chroma {
8587
template <typename T>
8688
struct color {
89+
color(color const&) = delete;
90+
color& operator=(color const&) = delete;
91+
color(color&&) = default;
92+
color& operator=(color&&) = default;
93+
8794
protected:
8895
constexpr color() = default;
8996
friend T;
@@ -97,8 +104,9 @@ struct callable_from : chroma::color<T> {
97104

98105
consteval explicit(false)
99106
callable_from(std::meta::access_context ctx = std::meta::access_context::current()) {
100-
if (not _chroma_impl::is_viable(ctx.scope(), ^^T)) {
101-
panic(T::error_message);
107+
using enum _chroma_impl::Viability;
108+
if (_chroma_impl::viability_of(ctx.scope(), ^^T) == rejected) {
109+
_chroma_impl::panic(T::error_message);
102110
}
103111
}
104112

@@ -117,12 +125,13 @@ struct callable_from : chroma::color<T> {
117125

118126
template <typename T>
119127
struct not_callable_from {
120-
consteval explicit(false) not_callable_from(unchecked_context) {}
128+
consteval explicit(false) not_callable_from(_chroma_impl::unchecked_context) {}
121129

122130
consteval explicit(false)
123131
not_callable_from(std::meta::access_context ctx = std::meta::access_context::current()) {
124-
if (_chroma_impl::is_viable(ctx.scope(), ^^T)) {
125-
panic(T::error_message);
132+
using enum _chroma_impl::Viability;
133+
if (_chroma_impl::viability_of(ctx.scope(), ^^T) == accepted) {
134+
_chroma_impl::panic(T::error_message);
126135
}
127136
}
128137

0 commit comments

Comments
 (0)