From 592b68c7c9dd9c28eee6653ce74a37a061f31832 Mon Sep 17 00:00:00 2001 From: Evgeny Gorodetsky Date: Sat, 28 Dec 2024 20:34:40 +0300 Subject: [PATCH] Fix static-analysis issues: apply hidden friend pattern to binary operators --- .../ParallelRenderingApp.cpp | 11 +- .../ParallelRenderingApp.h | 9 +- .../Include/Methane/Data/AlignedAllocator.hpp | 8 +- .../RangeSet/Include/Methane/Data/Range.hpp | 42 +++---- .../Data/Types/Include/Methane/Data/Point.hpp | 61 +++++----- .../Data/Types/Include/Methane/Data/Rect.hpp | 96 ++++++++------- .../Types/Include/Methane/Graphics/Volume.hpp | 112 ++++++++++-------- .../Include/Methane/UserInterface/Types.hpp | 112 +++++++++++++++--- 8 files changed, 272 insertions(+), 179 deletions(-) diff --git a/Apps/07-ParallelRendering/ParallelRenderingApp.cpp b/Apps/07-ParallelRendering/ParallelRenderingApp.cpp index 325e166f1..3dd31a985 100644 --- a/Apps/07-ParallelRendering/ParallelRenderingApp.cpp +++ b/Apps/07-ParallelRendering/ParallelRenderingApp.cpp @@ -72,11 +72,12 @@ constexpr char const* g_app_variant_name = "Root Constants"; constexpr char const* g_app_variant_name = "Buffer Views"; #endif -bool ParallelRenderingApp::Settings::operator==(const Settings& other) const noexcept +bool operator==(const ParallelRenderingApp::Settings& left, + const ParallelRenderingApp::Settings& right) noexcept { META_FUNCTION_TASK(); - return std::tie(cubes_grid_size, render_thread_count, parallel_rendering_enabled) == - std::tie(other.cubes_grid_size, other.render_thread_count, other.parallel_rendering_enabled); + return std::tie(left.cubes_grid_size, left.render_thread_count, left.parallel_rendering_enabled) == + std::tie(right.cubes_grid_size, right.render_thread_count, right.parallel_rendering_enabled); } uint32_t ParallelRenderingApp::Settings::GetTotalCubesCount() const noexcept @@ -219,7 +220,7 @@ void ParallelRenderingApp::Init() frame.cubes_uniform_argument_binding_ptrs[0] = &frame.cubes_program_bindings[0].Get({ rhi::ShaderType::All, "g_uniforms" }); frame.cubes_program_bindings[0].SetName(fmt::format("Cube 0 Bindings {}", frame.index)); #else - const Data::Size uniform_data_size = MeshBuffers::GetUniformSize(); + static const Data::Size uniform_data_size = MeshBuffers::GetUniformSize(); frame.cubes_array.program_bindings_per_instance.resize(cubes_count); frame.cubes_array.program_bindings_per_instance[0] = render_state_settings.program.CreateBindings({ { @@ -245,7 +246,7 @@ void ParallelRenderingApp::Init() cube_program_bindings.SetName(fmt::format("Cube {} Bindings {}", cube_index, frame.index)); } #else - [&frame, &cube_array_buffers, uniform_data_size](const uint32_t cube_index) + [&frame, &cube_array_buffers](const uint32_t cube_index) { rhi::ProgramBindings& cube_program_bindings = frame.cubes_array.program_bindings_per_instance[cube_index]; cube_program_bindings = rhi::ProgramBindings(frame.cubes_array.program_bindings_per_instance[0], { diff --git a/Apps/07-ParallelRendering/ParallelRenderingApp.h b/Apps/07-ParallelRendering/ParallelRenderingApp.h index 98ddd8fcf..730eeb133 100644 --- a/Apps/07-ParallelRendering/ParallelRenderingApp.h +++ b/Apps/07-ParallelRendering/ParallelRenderingApp.h @@ -71,7 +71,7 @@ class ParallelRenderingApp final // NOSONAR - destructor required uint32_t render_thread_count = std::thread::hardware_concurrency(); bool parallel_rendering_enabled = true; - bool operator==(const Settings& other) const noexcept; + friend bool operator==(const Settings& left, const Settings& right) noexcept; uint32_t GetTotalCubesCount() const noexcept; uint32_t GetActiveRenderThreadCount() const noexcept; @@ -92,10 +92,6 @@ class ParallelRenderingApp final // NOSONAR - destructor required const Settings& GetSettings() const noexcept { return m_settings; } void SetSettings(const Settings& settings); -protected: - // IContextCallback override - void OnContextReleased(rhi::IContext& context) override; - private: struct CubeParameters { @@ -114,6 +110,9 @@ class ParallelRenderingApp final // NOSONAR - destructor required const std::vector& program_bindings_per_instance, uint32_t begin_instance_index, const uint32_t end_instance_index) const; + // IContextCallback override + void OnContextReleased(rhi::IContext& context) override; + Settings m_settings; gfx::Camera m_camera; rhi::RenderState m_render_state; diff --git a/Modules/Data/Primitives/Include/Methane/Data/AlignedAllocator.hpp b/Modules/Data/Primitives/Include/Methane/Data/AlignedAllocator.hpp index 65de6e1e4..df7c0df07 100644 --- a/Modules/Data/Primitives/Include/Methane/Data/AlignedAllocator.hpp +++ b/Modules/Data/Primitives/Include/Methane/Data/AlignedAllocator.hpp @@ -99,12 +99,14 @@ class AlignedAllocator return size_type(-1) / sizeof(value_type); } - bool operator!=(const AlignedAllocator& other) const + friend bool operator!=(const AlignedAllocator& left, + const AlignedAllocator& right) { - return !(*this == other); + return !(left == right); } - bool operator==(const AlignedAllocator&) const + friend bool operator==(const AlignedAllocator&, + const AlignedAllocator&) { return true; } diff --git a/Modules/Data/RangeSet/Include/Methane/Data/Range.hpp b/Modules/Data/RangeSet/Include/Methane/Data/Range.hpp index 084ef5997..4e950a415 100644 --- a/Modules/Data/RangeSet/Include/Methane/Data/Range.hpp +++ b/Modules/Data/RangeSet/Include/Methane/Data/Range.hpp @@ -50,17 +50,17 @@ class Range : Range(*init.begin(), *(init.begin() + 1)) { } - [[nodiscard]] bool operator==(const Range& other) const noexcept { return m_start == other.m_start && m_end == other.m_end; } - [[nodiscard]] bool operator!=(const Range& other) const noexcept { return !operator==(other); } - [[nodiscard]] bool operator< (const Range& other) const noexcept { return m_end <= other.m_start; } - [[nodiscard]] bool operator> (const Range& other) const noexcept { return m_start > other.end; } - - [[nodiscard]] ScalarT GetStart() const noexcept { return m_start; } - [[nodiscard]] ScalarT GetEnd() const noexcept { return m_end; } - [[nodiscard]] ScalarT GetMin() const noexcept { return m_start; } - [[nodiscard]] ScalarT GetMax() const noexcept { return m_end; } - [[nodiscard]] ScalarT GetLength() const noexcept { return m_end - m_start; } - [[nodiscard]] bool IsEmpty() const noexcept { return m_start == m_end; } + [[nodiscard]] friend bool operator==(const Range& left, const Range& right) noexcept { return left.m_start == right.m_start && left.m_end == right.m_end; } + [[nodiscard]] friend bool operator!=(const Range& left, const Range& right) noexcept { return !(left == right); } + [[nodiscard]] friend bool operator< (const Range& left, const Range& right) noexcept { return left.m_end <= right.m_start; } + [[nodiscard]] friend bool operator> (const Range& left, const Range& right) noexcept { return left.m_start > right.m_end; } + + [[nodiscard]] ScalarT GetStart() const noexcept { return m_start; } + [[nodiscard]] ScalarT GetEnd() const noexcept { return m_end; } + [[nodiscard]] ScalarT GetMin() const noexcept { return m_start; } + [[nodiscard]] ScalarT GetMax() const noexcept { return m_end; } + [[nodiscard]] ScalarT GetLength() const noexcept { return m_end - m_start; } + [[nodiscard]] bool IsEmpty() const noexcept { return m_start == m_end; } [[nodiscard]] bool IsAdjacent(const Range& other) const noexcept { return m_start == other.m_end || other.m_start == m_end; } [[nodiscard]] bool IsOverlapping(const Range& other) const noexcept { return m_start < other.m_end && other.m_start < m_end; } @@ -68,28 +68,28 @@ class Range [[nodiscard]] bool Contains(const Range& other) const noexcept { return m_start <= other.m_start && other.m_end <= m_end; } [[nodiscard]] - Range operator+(const Range& other) const // merge + friend Range operator+(const Range& left, const Range& right) // merge { META_FUNCTION_TASK(); - META_CHECK_DESCR(other, IsMergeable(other), "can not merge ranges which are not overlapping or adjacent"); - return Range(std::min(m_start, other.m_start), std::max(m_end, other.m_end)); + META_CHECK_DESCR(right, left.IsMergeable(right), "can not merge ranges which are not overlapping or adjacent"); + return Range(std::min(left.m_start, right.m_start), std::max(left.m_end, right.m_end)); } [[nodiscard]] - Range operator%(const Range& other) const // intersect + friend Range operator%(const Range& left, const Range& right) // intersect { META_FUNCTION_TASK(); - META_CHECK_DESCR(other, IsMergeable(other), "can not intersect ranges which are not overlapping or adjacent"); - return Range(std::max(m_start, other.m_start), std::min(m_end, other.m_end)); + META_CHECK_DESCR(right, left.IsMergeable(right), "can not intersect ranges which are not overlapping or adjacent"); + return Range(std::max(left.m_start, right.m_start), std::min(left.m_end, right.m_end)); } [[nodiscard]] - Range operator-(const Range& other) const // subtract + friend Range operator-(const Range& left, const Range& right) // subtract { META_FUNCTION_TASK(); - META_CHECK_DESCR(other, IsOverlapping(other), "can not subtract ranges which are not overlapping"); - META_CHECK_DESCR(other, !Contains(other) && !other.Contains(*this), "can not subtract ranges containing one another"); - return (m_start <= other.m_start) ? Range(m_start, other.m_start) : Range(other.m_end, m_end); + META_CHECK_DESCR(right, left.IsOverlapping(right), "can not subtract ranges which are not overlapping"); + META_CHECK_DESCR(right, !left.Contains(right) && !right.Contains(left), "can not subtract ranges containing one another"); + return (left.m_start <= right.m_start) ? Range(left.m_start, right.m_start) : Range(right.m_end, left.m_end); } [[nodiscard]] explicit operator bool() const noexcept { return !IsEmpty(); } diff --git a/Modules/Data/Types/Include/Methane/Data/Point.hpp b/Modules/Data/Types/Include/Methane/Data/Point.hpp index 400f3ec2b..93254fd54 100644 --- a/Modules/Data/Types/Include/Methane/Data/Point.hpp +++ b/Modules/Data/Types/Include/Methane/Data/Point.hpp @@ -134,109 +134,110 @@ class Point // NOSONAR - class has more than 35 methods } } - [[nodiscard]] bool operator==(const PointType& other) const noexcept + [[nodiscard]] friend bool operator==(const PointType& left, const PointType& right) noexcept { #if defined(__APPLE__) && defined(__x86_64__) // FIXME: workaround for HLSL++ issue (https://github.com/redorav/hlslpp/issues/61): // Integer vector comparison is working incorrectly on Intel based Macs with MacOS >= 11 - return AsArray() == other.AsArray(); + return left.AsArray() == right.AsArray(); #else - return hlslpp::all(m_vector == other.AsVector()); + return hlslpp::all(left.m_vector == right.AsVector()); #endif } - [[nodiscard]] bool operator<(const PointType& other) const noexcept + [[nodiscard]] friend bool operator<(const PointType& left, const PointType& right) noexcept { #if defined(__APPLE__) && defined(__x86_64__) // FIXME: workaround for HLSL++ issue (https://github.com/redorav/hlslpp/issues/61): // Integer vector comparison is working incorrectly on Intel based Macs with MacOS >= 11 for(size_t i = 0; i < size; ++i) - if ((*this)[i] >= other[i]) + if (left[i] >= right[i]) return false; return true; #else - return hlslpp::all(m_vector < other.AsVector()); + return hlslpp::all(left.m_vector < right.AsVector()); #endif } - [[nodiscard]] bool operator>(const PointType& other) const noexcept + [[nodiscard]] friend bool operator>(const PointType& left, const PointType& right) noexcept { #if defined(__APPLE__) && defined(__x86_64__) // FIXME: workaround for HLSL++ issue (https://github.com/redorav/hlslpp/issues/61): // Integer vector comparison is working incorrectly on Intel based Macs with MacOS >= 11 for(size_t i = 0; i < size; ++i) - if ((*this)[i] <= other[i]) + if (left[i] <= right[i]) return false; return true; #else - return hlslpp::all(m_vector > other.AsVector()); + return hlslpp::all(left.m_vector > right.AsVector()); #endif } - bool operator!=(const PointType& other) const noexcept { return !operator==(other); } - bool operator<=(const PointType& other) const noexcept { return hlslpp::all(m_vector <= other.AsVector()); } - bool operator>=(const PointType& other) const noexcept { return hlslpp::all(m_vector >= other.AsVector()); } + friend bool operator!=(const PointType& left, const PointType& right) noexcept { return !(left == right); } + friend bool operator<=(const PointType& left, const PointType& right) noexcept { return hlslpp::all(left.m_vector <= right.AsVector()); } + friend bool operator>=(const PointType& left, const PointType& right) noexcept { return hlslpp::all(left.m_vector >= right.AsVector()); } + + friend PointType operator+(const PointType& left, const PointType& right) noexcept { return PointType(left.m_vector + right.AsVector()); } + friend PointType operator-(const PointType& left, const PointType& right) noexcept { return PointType(left.m_vector - right.AsVector()); } - PointType operator+(const PointType& other) const noexcept { return PointType(m_vector + other.AsVector()); } - PointType operator-(const PointType& other) const noexcept { return PointType(m_vector - other.AsVector()); } PointType& operator+=(const PointType& other) noexcept { m_vector += other.AsVector(); return *this; } PointType& operator-=(const PointType& other) noexcept { m_vector -= other.AsVector(); return *this; } template - std::enable_if_t, PointType> operator*(M multiplier) const noexcept + friend std::enable_if_t, PointType> operator*(const PointType& point, M multiplier) noexcept { if constexpr (std::is_same_v) - return PointType(m_vector * multiplier); + return PointType(point.m_vector * multiplier); else { if constexpr (std::is_floating_point_v) - return PointType(Point(*this) * multiplier); + return PointType(Point(point) * multiplier); else - return PointType(m_vector * static_cast(multiplier)); + return PointType(point.m_vector * static_cast(multiplier)); } } template - std::enable_if_t, PointType> operator/(M divisor) const noexcept + friend std::enable_if_t, PointType> operator/(const PointType& point, M divisor) noexcept { if constexpr (std::is_same_v) - return PointType(m_vector / divisor); + return PointType(point.m_vector / divisor); else { if constexpr (std::is_floating_point_v) - return PointType(Point(*this) / divisor); + return PointType(Point(point) / divisor); else - return PointType(m_vector / static_cast(divisor)); + return PointType(point.m_vector / static_cast(divisor)); } } template - std::enable_if_t, PointType> operator*(const Point& multiplier) const noexcept + friend std::enable_if_t, PointType> operator*(const PointType& point, const Point& multiplier) noexcept { if constexpr (std::is_same_v) - return PointType(m_vector * multiplier.AsVector()); + return PointType(point.m_vector * multiplier.AsVector()); else { if constexpr (std::is_floating_point_v) { - return PointType(Point(static_cast>(*this).AsVector() * multiplier.AsVector())); + return PointType(Point(static_cast>(point).AsVector() * multiplier.AsVector())); } else - return PointType(m_vector * static_cast(multiplier).AsVector()); + return PointType(point.m_vector * static_cast(multiplier).AsVector()); } } template - std::enable_if_t, PointType> operator/(const Point& divisor) const noexcept + friend std::enable_if_t, PointType> operator/(const PointType& point, const Point& divisor) noexcept { if constexpr (std::is_same_v) - return PointType(m_vector / divisor.AsVector()); + return PointType(point.m_vector / divisor.AsVector()); else { if constexpr (std::is_floating_point_v) - return PointType(Point(static_cast>(*this).AsVector() / divisor.AsVector())); + return PointType(Point(static_cast>(point).AsVector() / divisor.AsVector())); else - return PointType(m_vector / static_cast(divisor).AsVector()); + return PointType(point.m_vector / static_cast(divisor).AsVector()); } } diff --git a/Modules/Data/Types/Include/Methane/Data/Rect.hpp b/Modules/Data/Types/Include/Methane/Data/Rect.hpp index cf83f6187..b285a390b 100644 --- a/Modules/Data/Types/Include/Methane/Data/Rect.hpp +++ b/Modules/Data/Types/Include/Methane/Data/Rect.hpp @@ -93,29 +93,29 @@ class RectSize // NOSONAR - class has more than 35 methods D GetPixelsCount() const noexcept { return m_width * m_height; } D GetLongestSide() const noexcept { return std::max(m_width, m_height); } - bool operator==(const RectSize& other) const noexcept - { return std::tie(m_width, m_height) == std::tie(other.m_width, other.m_height); } + friend bool operator==(const RectSize& left, const RectSize& right) noexcept + { return std::tie(left.m_width, left.m_height) == std::tie(right.m_width, right.m_height); } - bool operator!=(const RectSize& other) const noexcept - { return std::tie(m_width, m_height) != std::tie(other.m_width, other.m_height); } + friend bool operator!=(const RectSize& left, const RectSize& right) noexcept + { return std::tie(left.m_width, left.m_height) != std::tie(right.m_width, right.m_height); } - bool operator<=(const RectSize& other) const noexcept - { return m_width <= other.m_width && m_height <= other.m_height; } + friend bool operator<=(const RectSize& left, const RectSize& right) noexcept + { return left.m_width <= right.m_width && left.m_height <= right.m_height; } - bool operator<(const RectSize& other) const noexcept - { return m_width < other.m_width && m_height < other.m_height; } + friend bool operator<(const RectSize& left, const RectSize& right) noexcept + { return left.m_width < right.m_width && left.m_height < right.m_height; } - bool operator>=(const RectSize& other) const noexcept - { return m_width >= other.m_width && m_height >= other.m_height; } + friend bool operator>=(const RectSize& left, const RectSize& right) noexcept + { return left.m_width >= right.m_width && left.m_height >= right.m_height; } - bool operator>(const RectSize& other) const noexcept - { return m_width > other.m_width && m_height > other.m_height; } + friend bool operator>(const RectSize& left, const RectSize& right) noexcept + { return left.m_width > right.m_width && left.m_height > right.m_height; } - RectSize operator+(const RectSize& other) const noexcept - { return RectSize(m_width + other.m_width, m_height + other.m_height); } + friend RectSize operator+(const RectSize& left, const RectSize& right) noexcept + { return RectSize(left.m_width + right.m_width, left.m_height + right.m_height); } - RectSize operator-(const RectSize& other) const noexcept - { return RectSize(m_width - other.m_width, m_height - other.m_height); } + friend RectSize operator-(const RectSize& left, const RectSize& right) noexcept + { return RectSize(left.m_width - right.m_width, left.m_height - right.m_height); } RectSize& operator+=(const RectSize& other) noexcept { m_width += other.m_width; m_height += other.m_height; return *this; } @@ -124,29 +124,29 @@ class RectSize // NOSONAR - class has more than 35 methods { m_width -= other.m_width; m_height -= other.m_height; return *this; } template - std::enable_if_t, RectSize> operator*(M multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator*(const RectSize& sz, M multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { META_CHECK_GREATER_OR_EQUAL_DESCR(multiplier, 0, "rectangle size multiplier can not be less than zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) * multiplier), RoundCast(static_cast(m_height) * multiplier)); + return RectSize(RoundCast(static_cast(sz.m_width) * multiplier), RoundCast(static_cast(sz.m_height) * multiplier)); else - return RectSize(m_width * RoundCast(multiplier), m_height * RoundCast(multiplier)); + return RectSize(sz.m_width * RoundCast(multiplier), sz.m_height * RoundCast(multiplier)); } template - std::enable_if_t, RectSize> operator/(M divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator/(const RectSize& sz, M divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { META_CHECK_GREATER_DESCR(divisor, 0, "rectangle size divisor can not be less or equal to zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) / divisor), RoundCast(static_cast(m_height) / divisor)); + return RectSize(RoundCast(static_cast(sz.m_width) / divisor), RoundCast(static_cast(sz.m_height) / divisor)); else - return RectSize(m_width / RoundCast(divisor), m_height / RoundCast(divisor)); + return RectSize(sz.m_width / RoundCast(divisor), sz.m_height / RoundCast(divisor)); } template @@ -190,7 +190,7 @@ class RectSize // NOSONAR - class has more than 35 methods } template - std::enable_if_t, RectSize> operator*(const Point2T& multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator*(const RectSize& sz, const Point2T& multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -198,13 +198,15 @@ class RectSize // NOSONAR - class has more than 35 methods META_CHECK_GREATER_OR_EQUAL_DESCR(multiplier.GetY(), 0, "rectangle size multiplier coordinate y can not be less than zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) * multiplier.GetX()), RoundCast(static_cast(m_height) * multiplier.GetY())); + return RectSize(RoundCast(static_cast(sz.m_width) * multiplier.GetX()), + RoundCast(static_cast(sz.m_height) * multiplier.GetY())); else - return RectSize(m_width * RoundCast(multiplier.GetX()), m_height * RoundCast(multiplier.GetY())); + return RectSize(sz.m_width * RoundCast(multiplier.GetX()), + sz.m_height * RoundCast(multiplier.GetY())); } template - std::enable_if_t, RectSize> operator/(const Point2T& divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator/(const RectSize& sz, const Point2T& divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -212,9 +214,11 @@ class RectSize // NOSONAR - class has more than 35 methods META_CHECK_GREATER_OR_EQUAL_DESCR(divisor.GetY(), 0, "rectangle size divisor coordinate y can not be less than zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) / divisor.GetX()), RoundCast(static_cast(m_height) / divisor.GetY())); + return RectSize(RoundCast(static_cast(sz.m_width) / divisor.GetX()), + RoundCast(static_cast(sz.m_height) / divisor.GetY())); else - return RectSize(m_width / RoundCast(divisor.GetX()), m_height / RoundCast(divisor.GetY())); + return RectSize(sz.m_width / RoundCast(divisor.GetX()), + sz.m_height / RoundCast(divisor.GetY())); } template @@ -260,7 +264,7 @@ class RectSize // NOSONAR - class has more than 35 methods } template - std::enable_if_t, RectSize> operator*(const RectSize& multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator*(const RectSize& sz, const RectSize& multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -268,13 +272,15 @@ class RectSize // NOSONAR - class has more than 35 methods META_CHECK_GREATER_OR_EQUAL_DESCR(multiplier.GetHeight(), 0, "rectangle size multiplier height can not be less than zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) * multiplier.GetWidth()), RoundCast(static_cast(m_height) * multiplier.GetHeight())); + return RectSize(RoundCast(static_cast(sz.m_width) * multiplier.GetWidth()), + RoundCast(static_cast(sz.m_height) * multiplier.GetHeight())); else - return RectSize(m_width * RoundCast(multiplier.GetWidth()), m_height * RoundCast(multiplier.GetHeight())); + return RectSize(sz.m_width * RoundCast(multiplier.GetWidth()), + sz.m_height * RoundCast(multiplier.GetHeight())); } template - std::enable_if_t, RectSize> operator/(const RectSize& divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, RectSize> operator/(const RectSize& sz, const RectSize& divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -282,9 +288,11 @@ class RectSize // NOSONAR - class has more than 35 methods META_CHECK_GREATER_OR_EQUAL_DESCR(divisor.GetHeight(), 0, "rectangle size divisor height can not be less than zero"); } if constexpr (std::is_floating_point_v && std::is_integral_v) - return RectSize(RoundCast(static_cast(m_width) / divisor.GetWidth()), RoundCast(static_cast(m_height) / divisor.GetHeight())); + return RectSize(RoundCast(static_cast(sz.m_width) / divisor.GetWidth()), + RoundCast(static_cast(sz.m_height) / divisor.GetHeight())); else - return RectSize(m_width / RoundCast(divisor.GetWidth()), m_height / RoundCast(divisor.GetHeight())); + return RectSize(sz.m_width / RoundCast(divisor.GetWidth()), + sz.m_height / RoundCast(divisor.GetHeight())); } template @@ -378,35 +386,35 @@ struct Rect T GetTop() const noexcept { return origin.GetY(); } T GetBottom() const noexcept { return origin.GetY() + RoundCast(size.GetHeight()); } - bool operator==(const Rect& other) const noexcept + friend bool operator==(const Rect& left, const Rect& right) noexcept { - return std::tie(origin, size) == std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) == std::tie(right.origin, right.size); } - bool operator!=(const Rect& other) const noexcept + friend bool operator!=(const Rect& left, const Rect& right) noexcept { - return std::tie(origin, size) != std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) != std::tie(right.origin, right.size); } - bool operator<(const Rect& other) const noexcept + friend bool operator<(const Rect& left, const Rect& right) noexcept { - return std::tie(origin, size) < std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) < std::tie(right.origin, right.size); } template - std::enable_if_t, Rect> operator*(M multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, Rect> operator*(const Rect& rect, M multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) META_CHECK_GREATER_OR_EQUAL_DESCR(multiplier, 0, "rectangle multiplier can not be less than zero"); - return Rect(origin * multiplier, size * multiplier); + return Rect(rect.origin * multiplier, rect.size * multiplier); } template - std::enable_if_t, Rect> operator/(M divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, Rect> operator/(const Rect& rect, M divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) META_CHECK_GREATER_OR_EQUAL_DESCR(divisor, 0, "rectangle divisor can not be less than zero"); - return Rect(origin / divisor, size / divisor); + return Rect(rect.origin / divisor, rect.size / divisor); } template diff --git a/Modules/Graphics/Types/Include/Methane/Graphics/Volume.hpp b/Modules/Graphics/Types/Include/Methane/Graphics/Volume.hpp index 1d6c7b70e..2868e3da6 100644 --- a/Modules/Graphics/Types/Include/Methane/Graphics/Volume.hpp +++ b/Modules/Graphics/Types/Include/Methane/Graphics/Volume.hpp @@ -96,56 +96,64 @@ class VolumeSize // NOSONAR - class has more than 35 methods m_depth = depth; } - bool operator==(const VolumeSize& other) const noexcept - { return RectSize::operator==(other) && m_depth == other.m_depth; } + friend bool operator==(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) == right && left.m_depth == right.m_depth; } - bool operator!=(const VolumeSize& other) const noexcept - { return RectSize::operator!=(other) || m_depth != other.m_depth; } + friend bool operator!=(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) != right || left.m_depth != right.m_depth; } - bool operator<=(const VolumeSize& other) const noexcept - { return RectSize::operator<=(other) && m_depth <= other.m_depth; } + friend bool operator<=(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) <= right && left.m_depth <= right.m_depth; } - bool operator<(const VolumeSize& other) const noexcept - { return RectSize::operator<(other) && m_depth < other.m_depth; } + friend bool operator<(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) < right && left.m_depth < right.m_depth; } - bool operator>=(const VolumeSize& other) const noexcept - { return RectSize::operator>=(other) && m_depth >= other.m_depth; } + friend bool operator>=(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) >= right && left.m_depth >= right.m_depth; } - bool operator>(const VolumeSize& other) const noexcept - { return RectSize::operator>(other) && m_depth > other.m_depth; } + friend bool operator>(const VolumeSize& left, const VolumeSize& right) noexcept + { return static_cast&>(left) > right && left.m_depth > right.m_depth; } - VolumeSize operator+(const VolumeSize& other) const noexcept - { return VolumeSize(RectSize::operator+(other), m_depth + other.m_depth); } + friend VolumeSize operator+(const VolumeSize& left, const VolumeSize& right) noexcept + { return VolumeSize(static_cast&>(left) + right, left.m_depth + right.m_depth); } - VolumeSize operator-(const VolumeSize& other) const noexcept - { return VolumeSize(RectSize::operator-(other), m_depth - other.m_depth); } + friend VolumeSize operator-(const VolumeSize& left, const VolumeSize& right) noexcept + { return VolumeSize(static_cast&>(left) - right, left.m_depth - right.m_depth); } VolumeSize& operator+=(const VolumeSize& other) noexcept - { m_depth += other.m_depth; RectSize::operator+=(other); return *this; } + { + m_depth += other.m_depth; + RectSize::operator+=(other); + return *this; + } VolumeSize& operator-=(const VolumeSize& other) noexcept - { m_depth -= other.m_depth; RectSize::operator-=(other); return *this; } + { + m_depth -= other.m_depth; + RectSize::operator-=(other); + return *this; + } template - std::enable_if_t, VolumeSize> operator*(M multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator*(const VolumeSize& sz, M multiplier) noexcept(std::is_unsigned_v) { D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) * multiplier); + depth = Data::RoundCast(static_cast(sz.m_depth) * multiplier); else - depth = m_depth * Data::RoundCast(multiplier); - return VolumeSize(RectSize::operator*(multiplier), depth); + depth = sz.m_depth * Data::RoundCast(multiplier); + return VolumeSize(static_cast&>(sz) * multiplier, depth); } template - std::enable_if_t, VolumeSize> operator/(M divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator/(const VolumeSize& sz, M divisor) noexcept(std::is_unsigned_v) { D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) / divisor); + depth = Data::RoundCast(static_cast(sz.m_depth) / divisor); else - depth = m_depth / Data::RoundCast(divisor); - return VolumeSize(RectSize::operator/(divisor), depth); + depth = sz.m_depth / Data::RoundCast(divisor); + return VolumeSize(static_cast&>(sz) / divisor, depth); } template @@ -171,7 +179,7 @@ class VolumeSize // NOSONAR - class has more than 35 methods } template - std::enable_if_t, VolumeSize> operator*(const Point3T& multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator*(const VolumeSize& sz, const Point3T& multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -179,14 +187,14 @@ class VolumeSize // NOSONAR - class has more than 35 methods } D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) * multiplier.GetZ()); + depth = Data::RoundCast(static_cast(sz.m_depth) * multiplier.GetZ()); else - depth = m_depth * Data::RoundCast(multiplier.GetZ()); - return VolumeSize(RectSize::operator*(Point2T(multiplier.GetX(), multiplier.GetY())), depth); + depth = sz.m_depth * Data::RoundCast(multiplier.GetZ()); + return VolumeSize(static_cast&>(sz) * Point2T(multiplier.GetX(), multiplier.GetY()), depth); } template - std::enable_if_t, VolumeSize> operator/(const Point3T& divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator/(const VolumeSize& sz, const Point3T& divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -194,10 +202,10 @@ class VolumeSize // NOSONAR - class has more than 35 methods } D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) / divisor.GetZ()); + depth = Data::RoundCast(static_cast(sz.m_depth) / divisor.GetZ()); else - depth = m_depth / Data::RoundCast(divisor.GetZ()); - return VolumeSize(RectSize::operator/(Point2T(divisor.GetX(), divisor.GetY())), depth); + depth = sz.m_depth / Data::RoundCast(divisor.GetZ()); + return VolumeSize(static_cast&>(sz) / Point2T(divisor.GetX(), divisor.GetY()), depth); } template @@ -231,7 +239,7 @@ class VolumeSize // NOSONAR - class has more than 35 methods } template - std::enable_if_t, VolumeSize> operator*(const VolumeSize& multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator*(const VolumeSize& sz, const VolumeSize& multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -239,14 +247,14 @@ class VolumeSize // NOSONAR - class has more than 35 methods } D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) * multiplier.GetDepth()); + depth = Data::RoundCast(static_cast(sz.m_depth) * multiplier.GetDepth()); else - depth = m_depth * Data::RoundCast(multiplier.GetDepth()); - return VolumeSize(RectSize::operator*(multiplier), depth); + depth = sz.m_depth * Data::RoundCast(multiplier.GetDepth()); + return VolumeSize(static_cast&>(sz) * multiplier, depth); } template - std::enable_if_t, VolumeSize> operator/(const VolumeSize& divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, VolumeSize> operator/(const VolumeSize& sz, const VolumeSize& divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) { @@ -254,10 +262,10 @@ class VolumeSize // NOSONAR - class has more than 35 methods } D depth {}; if constexpr (std::is_floating_point_v && std::is_integral_v) - depth = Data::RoundCast(static_cast(m_depth) / divisor.GetDepth()); + depth = Data::RoundCast(static_cast(sz.m_depth) / divisor.GetDepth()); else - depth = m_depth / Data::RoundCast(divisor.GetDepth()); - return VolumeSize(RectSize::operator/(divisor), depth); + depth = sz.m_depth / Data::RoundCast(divisor.GetDepth()); + return VolumeSize(static_cast&>(sz) / divisor, depth); } template @@ -335,35 +343,35 @@ struct Volume // NOSONAR - class has more than 35 methods T GetNear() const noexcept { return origin.GetZ(); } T GetFar() const noexcept { return origin.GetZ() + Data::RoundCast(size.GetDepth()); } - bool operator==(const Volume& other) const noexcept + friend bool operator==(const Volume& left, const Volume& right) noexcept { - return std::tie(origin, size) == std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) == std::tie(right.origin, right.size); } - bool operator!=(const Volume& other) const noexcept + friend bool operator!=(const Volume& left, const Volume& right) noexcept { - return std::tie(origin, size) != std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) != std::tie(right.origin, right.size); } - bool operator<(const Volume& other) const noexcept + friend bool operator<(const Volume& left, const Volume& right) noexcept { - return std::tie(origin, size) < std::tie(other.origin, other.size); + return std::tie(left.origin, left.size) < std::tie(right.origin, right.size); } template - std::enable_if_t, Volume> operator*(M multiplier) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, Volume> operator*(const Volume& v, M multiplier) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) META_CHECK_GREATER_OR_EQUAL_DESCR(multiplier, 0, "volume multiplier can not be less than zero"); - return Volume{ origin * multiplier, size * multiplier }; + return Volume{ v.origin * multiplier, v.size * multiplier }; } template - std::enable_if_t, Volume> operator/(M divisor) const noexcept(std::is_unsigned_v) + friend std::enable_if_t, Volume> operator/(const Volume& v, M divisor) noexcept(std::is_unsigned_v) { if constexpr (std::is_signed_v) META_CHECK_GREATER_OR_EQUAL_DESCR(divisor, 0, "volume divisor can not be less than zero"); - return Volume{ origin / divisor, size / divisor }; + return Volume{ v.origin / divisor, v.size / divisor }; } template diff --git a/Modules/UserInterface/Types/Include/Methane/UserInterface/Types.hpp b/Modules/UserInterface/Types/Include/Methane/UserInterface/Types.hpp index 57f03fef6..f3e7560be 100644 --- a/Modules/UserInterface/Types/Include/Methane/UserInterface/Types.hpp +++ b/Modules/UserInterface/Types/Include/Methane/UserInterface/Types.hpp @@ -87,41 +87,115 @@ class UnitType : public BaseType // Disable Sonar Check for variadic arguments constructor, since it reports false positive about slicing for universal references template - explicit UnitType(Units units, BaseArgs&&... base_args) noexcept : BaseType(std::forward(base_args)...), m_units(units) { } //NOSONAR + explicit UnitType(Units units, BaseArgs&&... base_args) noexcept + : BaseType(std::forward(base_args)...) + , m_units(units) + { } template>> - explicit UnitType(const UnitType& size) noexcept : UnitType(size.GetUnits(), size.GetWidth(), size.GetHeight()) { } + explicit UnitType(const UnitType& size) noexcept + : UnitType(size.GetUnits(), size.GetWidth(), size.GetHeight()) + { } Units GetUnits() const noexcept { return m_units; } - template bool operator==(const T& other) const noexcept { return BaseType::operator==(static_cast(other)) && m_units == other.GetUnits(); } - template bool operator!=(const T& other) const noexcept { return BaseType::operator!=(static_cast(other)) || m_units != other.GetUnits(); } + friend bool operator==(const UnitType& left, const UnitType& right) noexcept + { return left == static_cast(right) && left.m_units == right.GetUnits(); } - template bool operator<=(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return BaseType::operator<=(other); } - template bool operator<(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return BaseType::operator<(other); } - template bool operator>=(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return BaseType::operator>=(other); } - template bool operator>(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return BaseType::operator>(other); } + friend bool operator!=(const UnitType& left, const UnitType& right) noexcept + { return left != static_cast(right) || left.m_units != right.GetUnits(); } - template UnitType operator+(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return UnitType(m_units, BaseType::operator+(other)); } - template UnitType operator-(const T& other) const { META_CHECK_EQUAL(other.GetUnits(), m_units); return UnitType(m_units, BaseType::operator-(other)); } - template UnitType& operator+=(const T& other) { META_CHECK_EQUAL(other.GetUnits(), m_units); BaseType::operator+=(other); return *this; } - template UnitType& operator-=(const T& other) { META_CHECK_EQUAL(other.GetUnits(), m_units); BaseType::operator-=(other); return *this; } + friend bool operator<=(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return static_cast(left) <= right; + } + + friend bool operator<(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return static_cast(left) < right; + } + + friend bool operator>=(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return static_cast(left) >= right; + } + + friend bool operator>(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return static_cast(left) > right; + } + + friend UnitType operator+(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return UnitType(left.m_units, static_cast(left) + right); + } + + friend UnitType operator-(const UnitType& left, const UnitType& right) + { + META_CHECK_EQUAL(right.GetUnits(), left.m_units); + return UnitType(left.m_units, static_cast(left) - right); + } + + template friend UnitType operator*(const UnitType& p, T&& multiplier) noexcept + { + return UnitType(p.m_units, static_cast(p) * std::forward(multiplier)); + } - template UnitType operator*(T&& multiplier) const noexcept { return UnitType(m_units, BaseType::operator*(std::forward(multiplier))); } - template UnitType operator/(T&& divisor) const noexcept { return UnitType(m_units, BaseType::operator/(std::forward(divisor))); } - template UnitType& operator*=(T&& multiplier) noexcept { BaseType::operator*=(std::forward(multiplier)); return *this; } - template UnitType& operator/=(T&& divisor) noexcept { BaseType::operator/=(std::forward(divisor)); return *this; } + template friend UnitType operator/(const UnitType& p, T&& divisor) noexcept + { + return UnitType(p.m_units, static_cast(p) / std::forward(divisor)); + } + + UnitType& operator+=(const UnitType& other) + { + META_CHECK_EQUAL(other.GetUnits(), m_units); + BaseType::operator+=(other); + return *this; + } + + UnitType& operator-=(const UnitType& other) + { + META_CHECK_EQUAL(other.GetUnits(), m_units); + BaseType::operator-=(other); + return *this; + } + + template UnitType& operator*=(T&& multiplier) noexcept + { + BaseType::operator*=(std::forward(multiplier)); + return *this; + } + + template UnitType& operator/=(T&& divisor) noexcept + { + BaseType::operator/=(std::forward(divisor)); + return *this; + } BaseType& AsBase() noexcept { return static_cast(*this); } const BaseType& AsBase() const noexcept { return static_cast(*this); } template - EnableReturnTypeIf, UnitType>> GetUnitOrigin() const noexcept { return UnitType>(m_units, BaseType::origin); } + EnableReturnTypeIf, UnitType>> GetUnitOrigin() const noexcept + { + return UnitType>(m_units, BaseType::origin); + } template - EnableReturnTypeIf, UnitType>> GetUnitSize() const noexcept { return UnitType>(m_units, BaseType::size); } + EnableReturnTypeIf, UnitType>> GetUnitSize() const noexcept + { + return UnitType>(m_units, BaseType::size); + } - explicit operator std::string() const { return fmt::format("{:s} in {:s}", BaseType::operator std::string(), GetUnitsName(m_units)); } + explicit operator std::string() const + { + return fmt::format("{:s} in {:s}", BaseType::operator std::string(), GetUnitsName(m_units)); + } private: Units m_units = Units::Pixels;