@@ -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
8183template <typename... Ts>
82- constexpr _chroma_impl::AssumedColors <Ts...> assume_color{};
84+ constexpr _chroma_impl::assumed_colors <Ts...> assume_color{};
8385
8486namespace chroma {
8587template <typename T>
8688struct color {
89+ color(color const&) = delete;
90+ color& operator=(color const&) = delete;
91+ color(color&&) = default;
92+ color& operator=(color&&) = default;
93+
8794protected:
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
118126template <typename T>
119127struct 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