--- 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 {