58 { |
58 { |
59 using type = std::remove_reference_t<R>&; |
59 using type = std::remove_reference_t<R>&; |
60 }; |
60 }; |
61 |
61 |
62 template<typename T, typename R> |
62 template<typename T, typename R> |
|
63 struct transfer_reference<const T&, R> |
|
64 { |
|
65 using type = const std::remove_reference_t<R>&; |
|
66 }; |
|
67 |
|
68 template<typename T, typename R> |
63 struct transfer_reference<T&&, R> |
69 struct transfer_reference<T&&, R> |
64 { |
70 { |
65 using type = std::remove_reference_t<R>&&; |
71 using type = std::remove_reference_t<R>&&; |
66 }; |
72 }; |
67 |
73 |
86 Triangle, |
92 Triangle, |
87 Quadrilateral, |
93 Quadrilateral, |
88 ConditionalEdge>>; |
94 ConditionalEdge>>; |
89 |
95 |
90 template<typename T> |
96 template<typename T> |
91 struct remove_color { using type = T; }; |
97 struct remove_color {}; |
92 |
98 |
93 template<typename T> |
99 template<typename T> |
94 struct remove_color<Colored<T>> { using type = T; }; |
100 struct remove_color<Colored<T>> { using type = T; }; |
95 |
101 |
96 template<typename T> |
102 template<typename T> |
97 struct remove_color<Colored<T>&> { using type = T&; }; |
103 struct remove_color<Colored<T>&> { using type = T&; }; |
98 |
104 |
99 template<typename T> |
105 template<typename T> |
|
106 struct remove_color<const Colored<T>&> { using type = const T&; }; |
|
107 |
|
108 template<typename T> |
100 struct remove_color<Colored<T>&&> { using type = T&&; }; |
109 struct remove_color<Colored<T>&&> { using type = T&&; }; |
101 |
110 |
102 template<typename T> |
111 template<typename T> |
103 using remove_color_t = typename remove_color<T>::type; |
112 using remove_color_t = typename remove_color<T>::type; |
104 |
113 |
|
114 static_assert(std::is_same_v<remove_color_t<Colored<Triangle>>, Triangle>); |
|
115 static_assert(std::is_same_v<remove_color_t<Colored<Triangle>&>, Triangle&>); |
|
116 static_assert(std::is_same_v<remove_color_t<const Colored<Triangle>&>, const Triangle&>); |
|
117 |
105 template<typename T> |
118 template<typename T> |
106 constexpr remove_color_t<T&&> extract_colored(T&& x) |
119 constexpr remove_color_t<T&&> extract_colored(T&& x) |
107 { |
120 { |
108 return static_cast<remove_color_t<T&&>>(x); |
121 return static_cast<remove_color_t<T&&>>(x); |
109 } |
122 } |
110 |
123 |
111 template<typename Ret, typename T> |
124 template<typename Ret, typename Fn1, typename Fn2, typename Fn3, typename Fn4, typename T> |
112 constexpr auto visitPolygon( |
125 constexpr auto visitPolygon(Fn1&& f1, Fn2&& f2, Fn3&& f3, Fn4&& f4, T&& element) |
113 std::function<Ret(transfer_reference_t<T&&, LineSegment>)> f1, |
126 { |
114 std::function<Ret(transfer_reference_t<T&&, Triangle>)> f2, |
127 if (std::holds_alternative<LineSegment>(element)) { |
115 std::function<Ret(transfer_reference_t<T&&, Quadrilateral>)> f3, |
128 return f1(std::get<LineSegment>(element)); |
116 std::function<Ret(transfer_reference_t<T&&, ConditionalEdge>)> f4, |
129 } |
117 T&& element) |
130 else if (std::holds_alternative<Triangle>(element)) { |
118 { |
131 return f2(std::get<Triangle>(element)); |
119 return std::visit(overloaded{f1, f2, f3, f4}, extract_colored(element)); |
132 } |
|
133 else if (std::holds_alternative<Quadrilateral>(element)) { |
|
134 return f3(std::get<Quadrilateral>(element)); |
|
135 } |
|
136 else { |
|
137 return f4(std::get<ConditionalEdge>(element)); |
|
138 } |
120 } |
139 } |
121 |
140 |
122 template<typename T, typename Fn> |
141 template<typename T, typename Fn> |
123 constexpr void visitPoints(T&& element, Fn func) |
142 constexpr void visitPoints(Fn&& func, T&& element) |
124 { |
143 { |
125 visitPolygon<void>( |
144 visitPolygon<void>( |
126 [&func](transfer_reference_t<T&&, LineSegment> edge) |
145 [&func](transfer_reference_t<T&&, LineSegment> edge) |
127 { |
146 { |
128 func(edge.p1); |
147 func(edge.p1); |