src/model.h

changeset 210
232e7634cc8a
parent 206
654661eab7f3
child 211
b27b90fb993f
--- a/src/model.h	Thu Jun 09 11:51:42 2022 +0300
+++ b/src/model.h	Thu Jun 09 13:32:55 2022 +0300
@@ -47,6 +47,30 @@
 
 struct Empty {};
 
+template<typename T, typename R>
+struct transfer_reference
+{
+	using type = std::remove_reference_t<R>;
+};
+
+template<typename T, typename R>
+struct transfer_reference<T&, R>
+{
+	using type = std::remove_reference_t<R>&;
+};
+
+template<typename T, typename R>
+struct transfer_reference<T&&, R>
+{
+	using type = std::remove_reference_t<R>&&;
+};
+
+template<typename T, typename R>
+using transfer_reference_t = typename transfer_reference<T, R>::type;
+static_assert(std::is_same_v<transfer_reference_t<int, char>, char>);
+static_assert(std::is_same_v<transfer_reference_t<int&, char>, char&>);
+static_assert(std::is_same_v<transfer_reference_t<int&&, char>, char&&>);
+
 using ModelElement = std::variant<
 	Colored<SubfileReference>,
 	Colored<LineSegment>,
@@ -57,6 +81,76 @@
 	Empty,
 	ParseError>;
 
+using PolygonElement = Colored<std::variant<
+	LineSegment,
+	Triangle,
+	Quadrilateral,
+	ConditionalEdge>>;
+
+template<typename T>
+struct remove_color { using type = T; };
+
+template<typename T>
+struct remove_color<Colored<T>> { using type = T; };
+
+template<typename T>
+struct remove_color<Colored<T>&> { using type = T&; };
+
+template<typename T>
+struct remove_color<Colored<T>&&> { using type = T&&; };
+
+template<typename T>
+using remove_color_t = typename remove_color<T>::type;
+
+template<typename T>
+constexpr remove_color_t<T&&> extract_colored(T&& x)
+{
+	return static_cast<remove_color_t<T&&>>(x);
+}
+
+template<typename Ret, typename T>
+constexpr auto visitPolygon(
+	std::function<Ret(transfer_reference_t<T&&, LineSegment>)> f1,
+	std::function<Ret(transfer_reference_t<T&&, Triangle>)> f2,
+	std::function<Ret(transfer_reference_t<T&&, Quadrilateral>)> f3,
+	std::function<Ret(transfer_reference_t<T&&, ConditionalEdge>)> f4,
+	T&& element)
+{
+	return std::visit(overloaded{f1, f2, f3, f4}, extract_colored(element));
+}
+
+template<typename T, typename Fn>
+constexpr void visitPoints(T&& element, Fn func)
+{
+	visitPolygon<void>(
+		[&func](transfer_reference_t<T&&, LineSegment> edge)
+		{
+			func(edge.p1);
+			func(edge.p2);
+		},
+		[&func](transfer_reference_t<T&&, Triangle>& tri)
+		{
+			func(tri.p1);
+			func(tri.p2);
+			func(tri.p3);
+		},
+		[&func](transfer_reference_t<T&&, Quadrilateral>& quad)
+		{
+			func(quad.p1);
+			func(quad.p2);
+			func(quad.p3);
+			func(quad.p4);
+		},
+		[&func](transfer_reference_t<T&&, ConditionalEdge>& cedge)
+		{
+			func(cedge.p1);
+			func(cedge.p2);
+			func(cedge.c1);
+			func(cedge.c2);
+		},
+		element);
+}
+
 QString modelElementToString(const ModelElement& element);
 struct ModelId
 {

mercurial