--- a/src/model.h Thu Jun 09 13:32:55 2022 +0300 +++ b/src/model.h Thu Jun 09 19:11:27 2022 +0300 @@ -60,6 +60,12 @@ }; template<typename T, typename R> +struct transfer_reference<const T&, R> +{ + using type = const std::remove_reference_t<R>&; +}; + +template<typename T, typename R> struct transfer_reference<T&&, R> { using type = std::remove_reference_t<R>&&; @@ -88,7 +94,7 @@ ConditionalEdge>>; template<typename T> -struct remove_color { using type = T; }; +struct remove_color {}; template<typename T> struct remove_color<Colored<T>> { using type = T; }; @@ -97,30 +103,43 @@ struct remove_color<Colored<T>&> { using type = T&; }; template<typename T> +struct remove_color<const Colored<T>&> { using type = const T&; }; + +template<typename T> struct remove_color<Colored<T>&&> { using type = T&&; }; template<typename T> using remove_color_t = typename remove_color<T>::type; +static_assert(std::is_same_v<remove_color_t<Colored<Triangle>>, Triangle>); +static_assert(std::is_same_v<remove_color_t<Colored<Triangle>&>, Triangle&>); +static_assert(std::is_same_v<remove_color_t<const Colored<Triangle>&>, const Triangle&>); + 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) +template<typename Ret, typename Fn1, typename Fn2, typename Fn3, typename Fn4, typename T> +constexpr auto visitPolygon(Fn1&& f1, Fn2&& f2, Fn3&& f3, Fn4&& f4, T&& element) { - return std::visit(overloaded{f1, f2, f3, f4}, extract_colored(element)); + if (std::holds_alternative<LineSegment>(element)) { + return f1(std::get<LineSegment>(element)); + } + else if (std::holds_alternative<Triangle>(element)) { + return f2(std::get<Triangle>(element)); + } + else if (std::holds_alternative<Quadrilateral>(element)) { + return f3(std::get<Quadrilateral>(element)); + } + else { + return f4(std::get<ConditionalEdge>(element)); + } } template<typename T, typename Fn> -constexpr void visitPoints(T&& element, Fn func) +constexpr void visitPoints(Fn&& func, T&& element) { visitPolygon<void>( [&func](transfer_reference_t<T&&, LineSegment> edge)