diff --git a/src/cata_inline.h b/src/cata_inline.h new file mode 100644 index 0000000000000..4eb25ef629902 --- /dev/null +++ b/src/cata_inline.h @@ -0,0 +1,13 @@ +#pragma once +#ifndef CATA_SRC_CATA_INLINE_H +#define CATA_SRC_CATA_INLINE_H + +#ifndef CATA_FORCEINLINE +#ifdef _MSC_VER +#define CATA_FORCEINLINE __forceinline +#else +#define CATA_FORCEINLINE inline __attribute__((always_inline)) +#endif +#endif + +#endif // CATA_SRC_CATA_INLINE_H diff --git a/src/coordinates.h b/src/coordinates.h index 0334705a8459f..2b64e805708bc 100644 --- a/src/coordinates.h +++ b/src/coordinates.h @@ -11,6 +11,7 @@ #include #include +#include "cata_inline.h" #include "coordinate_conversions.h" #include "coords_fwd.h" #include "cuboid_rectangle.h" @@ -115,9 +116,10 @@ class coord_point_base Point raw_; }; -template +template class coord_point_mut : public coord_point_base { + protected: using base = coord_point_base; public: @@ -164,318 +166,361 @@ class coord_point_mut : public coord_point_base } }; -template -class coord_point_mut< Point, Subpoint, true> : public coord_point_base +template +class coord_point_ob : public + coord_point_mut> { - using base = coord_point_base; + using base = coord_point_mut>; public: - // Default constructed point is always inbounds. - constexpr coord_point_mut() = default; - - // TODO: move the const accessors into base when cata-unsequenced-calls is fixed. - constexpr const Point &raw() const { - return this->raw_; - } - - constexpr auto x() const { - return raw().x; - } - constexpr auto y() const { - return raw().y; - } - constexpr auto z() const { - return raw().z; - } - - protected: - // Hide the constructors so they are not used by accident. - // - // Use make_unchecked instead. - explicit constexpr coord_point_mut( const Point &p ) : base( p ) {} - template - constexpr coord_point_mut( const Subpoint &p, T z ) : base( p.raw(), z ) {} - template - constexpr coord_point_mut( T x, T y ) : base( x, y ) {} - template - constexpr coord_point_mut( T x, T y, T z ) : base( x, y, z ) {} -}; - -template -class coord_point : public - coord_point_mut, InBounds> -{ - using base = coord_point_mut, InBounds>; using base::base; - public: static constexpr int dimension = Point::dimension; - using this_as_tripoint_ob = coord_point; - using this_as_point = coord_point; - using this_as_ob = coord_point; + static constexpr bool is_inbounds = false; + using this_as_tripoint = coord_point_ob; + using this_as_point = coord_point_ob; + using this_as_ob = coord_point_ob; + using this_as_tripoint_ob = coord_point_ob; - // Explicit functions to construct inbounds versions without doing any - // bounds checking. Only use these with a very good reason, when you - // are completely sure the result will be inbounds. template - static constexpr coord_point make_unchecked( T x, T y ) { - return coord_point( x, y ); + static constexpr coord_point_ob make_unchecked( T x, T y ) { + return coord_point_ob( x, y ); } template - static constexpr coord_point make_unchecked( T x, T y, T z ) { - return coord_point( x, y, z ); + static constexpr coord_point_ob make_unchecked( T x, T y, T z ) { + return coord_point_ob( x, y, z ); } - static constexpr coord_point make_unchecked( const this_as_ob &other ) { - return coord_point( other.raw() ); + static constexpr coord_point_ob make_unchecked( const base &other ) { + return coord_point_ob( other ); } - static constexpr coord_point make_unchecked( const Point &other ) { - return coord_point( other ); + static constexpr coord_point_ob make_unchecked( const Point &other ) { + return coord_point_ob( other ); } template - static constexpr coord_point make_unchecked( const this_as_point &other, T z ) { - return coord_point( other, z ); + static constexpr coord_point_ob make_unchecked( const this_as_point &other, T z ) { + return coord_point_ob( other, z ); } template - static constexpr coord_point make_unchecked( const point &other, T z ) { - return coord_point( other.x, other.y, z ); - } - - // Allow implicit conversions from inbounds to out of bounds. - // NOLINTNEXTLINE(google-explicit-constructor) - operator this_as_ob() const { - return this_as_ob( this->raw() ); + static constexpr coord_point_ob make_unchecked( const point &other, T z ) { + return coord_point_ob( other.x, other.y, z ); } constexpr auto xy() const { - return this_as_point::make_unchecked( this->raw().xy() ); + return this_as_point( this->raw().xy() ); } - friend inline this_as_ob operator+( const coord_point &l, const point &r ) { + friend inline this_as_ob operator+( const coord_point_ob &l, const point &r ) { return this_as_ob( l.raw() + r ); } - friend inline this_as_tripoint_ob operator+( const coord_point &l, const tripoint &r ) { + friend inline this_as_tripoint_ob operator+( const coord_point_ob &l, const tripoint &r ) { return this_as_tripoint_ob( l.raw() + r ); } - friend inline this_as_ob operator+( const point &l, const coord_point &r ) { + friend inline this_as_ob operator+( const point &l, const coord_point_ob &r ) { return this_as_ob( l + r.raw() ); } - friend inline this_as_tripoint_ob operator+( const tripoint &l, const coord_point &r ) { + friend inline this_as_tripoint_ob operator+( const tripoint &l, const coord_point_ob &r ) { return this_as_tripoint_ob( l + r.raw() ); } - friend inline this_as_ob operator-( const coord_point &l, const point &r ) { + friend inline this_as_ob operator-( const coord_point_ob &l, const point &r ) { return this_as_ob( l.raw() - r ); } - friend inline this_as_tripoint_ob operator-( const coord_point &l, const tripoint &r ) { + friend inline this_as_tripoint_ob operator-( const coord_point_ob &l, const tripoint &r ) { return this_as_tripoint_ob( l.raw() - r ); } }; template -constexpr inline coord_point &operator+=( coord_point - &me, const coord_point &r ) +class coord_point_ib : public coord_point_ob +{ + using base = coord_point_ob; + using base::base; + + public: + static constexpr bool is_inbounds = true; + using this_as_tripoint = coord_point_ib; + using this_as_point = coord_point_ib; + using this_as_tripoint_ob = coord_point_ob; + using this_as_ob = base; + + // Explicit functions to construct inbounds versions without doing any + // bounds checking. Only use these with a very good reason, when you + // are completely sure the result will be inbounds. + template + static constexpr coord_point_ib make_unchecked( T x, T y ) { + return coord_point_ib( x, y ); + } + template + static constexpr coord_point_ib make_unchecked( T x, T y, T z ) { + return coord_point_ib( x, y, z ); + } + static constexpr coord_point_ib make_unchecked( const base &other ) { + return coord_point_ib( other ); + } + static constexpr coord_point_ib make_unchecked( const Point &other ) { + return coord_point_ib( other ); + } + template + static constexpr coord_point_ib make_unchecked( const this_as_point &other, T z ) { + return coord_point_ib( other, z ); + } + template + static constexpr coord_point_ib make_unchecked( const point &other, T z ) { + return coord_point_ib( other.x, other.y, z ); + } + + // Allow implicit conversions from inbounds to out of bounds. + // NOLINTNEXTLINE(google-explicit-constructor) + operator const this_as_ob &() const { + return *this; + } + + const this_as_ob &as_ob() const { + return *this; + } + + constexpr auto xy() const { + return this_as_point::make_unchecked( this->raw().xy() ); + } +}; + +template +constexpr inline coord_point_ob &operator+= +( coord_point_ob + &me, const coord_point_ob &r ) { me.raw() += r.raw(); return me; } template -constexpr inline coord_point &operator-=( coord_point - &me, const coord_point &r ) +constexpr inline coord_point_ob &operator-= +( coord_point_ob + &me, const coord_point_ob &r ) { me.raw() -= r.raw(); return me; } template -constexpr inline coord_point &operator+=( coord_point - &me, const point &r ) +constexpr inline coord_point_ob &operator+= +( coord_point_ob + &me, const point &r ) { me.raw() += r; return me; } template -constexpr inline coord_point &operator-=( coord_point - &me, const point &r ) +constexpr inline coord_point_ob &operator-= +( coord_point_ob + &me, const point &r ) { me.raw() -= r; return me; } template -constexpr inline coord_point &operator+=( coord_point - &me, const tripoint &r ) +constexpr inline coord_point_ob &operator+= +( coord_point_ob + &me, const tripoint &r ) { me.raw() += r; return me; } template -constexpr inline coord_point &operator-=( coord_point - &me, const tripoint &r ) +constexpr inline coord_point_ob &operator-= +( coord_point_ob + &me, const tripoint &r ) { me.raw() -= r; return me; } -template -constexpr inline bool operator==( const coord_point &l, - const coord_point &r ) +template +constexpr inline bool operator==( const coord_point_ob &l, + const coord_point_ob &r ) { return l.raw() == r.raw(); } -template -constexpr inline bool operator!=( const coord_point &l, - const coord_point &r ) +template +constexpr inline bool operator!=( const coord_point_ob &l, + const coord_point_ob &r ) { return l.raw() != r.raw(); } -template -constexpr inline bool operator<( const coord_point &l, - const coord_point &r ) +template +constexpr inline bool operator<( const coord_point_ob &l, + const coord_point_ob &r ) { return l.raw() < r.raw(); } -template +template constexpr inline auto operator+( - const coord_point &l, - const coord_point &r ) + const coord_point_ob &l, + const coord_point_ob &r ) { using PointResult = decltype( PointL() + PointR() ); - return coord_point( l.raw() + r.raw() ); + return coord_point_ob( l.raw() + r.raw() ); } -template < typename PointL, typename PointR, origin OriginR, scale Scale, bool InBounds, +template < typename PointL, typename PointR, origin OriginR, scale Scale, // enable_if to prevent ambiguity with above when both args are // relative typename = std::enable_if_t < OriginR != origin::relative >> constexpr inline auto operator+( - const coord_point &l, - const coord_point &r ) + const coord_point_ob &l, + const coord_point_ob &r ) { using PointResult = decltype( PointL() + PointR() ); - return coord_point( l.raw() + r.raw() ); + return coord_point_ob( l.raw() + r.raw() ); } -template +template constexpr inline auto operator-( - const coord_point &l, - const coord_point &r ) + const coord_point_ob &l, + const coord_point_ob &r ) { using PointResult = decltype( PointL() + PointR() ); - return coord_point( l.raw() - r.raw() ); + return coord_point_ob( l.raw() - r.raw() ); } -template < typename PointL, typename PointR, origin Origin, scale Scale, bool LhsInBounds, - bool RhsInBounds, +template < typename PointL, typename PointR, origin Origin, scale Scale, // enable_if to prevent ambiguity with above when both args are // relative typename = std::enable_if_t < Origin != origin::relative >> constexpr inline auto operator-( - const coord_point &l, - const coord_point &r ) + const coord_point_ob &l, + const coord_point_ob &r ) { using PointResult = decltype( PointL() + PointR() ); - return coord_point( l.raw() - r.raw() ); + return coord_point_ob( l.raw() - r.raw() ); } // Only relative points can be multiplied by a constant template -constexpr inline coord_point operator*( - int l, const coord_point &r ) +constexpr inline coord_point_ob operator*( + int l, const coord_point_ob &r ) { - return coord_point( l * r.raw() ); + return coord_point_ob( l * r.raw() ); } template -constexpr inline coord_point operator*( - const coord_point &r, int l ) +constexpr inline coord_point_ob operator*( + const coord_point_ob &r, int l ) { - return coord_point( r.raw() * l ); + return coord_point_ob( r.raw() * l ); } -template +template inline std::ostream &operator<<( std::ostream &os, - const coord_point &p ) + const coord_point_ob &p ) { return os << p.raw(); } -template -constexpr inline coord_point < Point, Origin, Scale, LhsInBounds &&RhsInBounds > -coord_min( const coord_point &l, - const coord_point &r ) +template +constexpr inline coord_point < Point, Origin, Scale> +coord_min( const coord_point_ob &l, + const coord_point_ob &r ) +{ + return coord_point < Point, Origin, Scale >::make_unchecked( std::min( l.x(), r.x() ), + std::min( l.y(), r.y() ), std::min( l.z(), + r.z() ) ); +} + +template +constexpr inline coord_point < Point, Origin, Scale > +coord_max( const coord_point_ob &l, + const coord_point_ob &r ) +{ + return coord_point < Point, Origin, Scale >::make_unchecked( std::max( l.x(), r.x() ), + std::max( l.y(), r.y() ), std::max( l.z(), + r.z() ) ); +} + +// Min and max of inbounds points results in an inbounds point. + +template +constexpr inline coord_point_ib < Point, Origin, Scale> +coord_min( const coord_point_ib &l, + const coord_point_ib &r ) { - return coord_point < Point, Origin, Scale, LhsInBounds && - RhsInBounds >::make_unchecked( std::min( l.x(), r.x() ), std::min( l.y(), r.y() ), std::min( l.z(), - r.z() ) ); + return coord_point_ib < Point, Origin, Scale >::make_unchecked( std::min( l.x(), r.x() ), + std::min( l.y(), r.y() ), std::min( l.z(), + r.z() ) ); } -template -constexpr inline coord_point < Point, Origin, Scale, LhsInBounds &&RhsInBounds > -coord_max( const coord_point &l, - const coord_point &r ) +template +constexpr inline coord_point_ib < Point, Origin, Scale > +coord_max( const coord_point_ib &l, + const coord_point_ib &r ) { - return coord_point < Point, Origin, Scale, LhsInBounds && - RhsInBounds >::make_unchecked( std::max( l.x(), r.x() ), std::max( l.y(), r.y() ), std::max( l.z(), - r.z() ) ); + return coord_point_ib < Point, Origin, Scale >::make_unchecked( std::max( l.x(), r.x() ), + std::max( l.y(), r.y() ), std::max( l.z(), + r.z() ) ); } -template +template struct project_to_impl; -template -struct project_to_impl { - template - coord_point operator()( - const coord_point &src ) { +template +struct project_to_impl { + template class coord, typename Point, origin Origin, scale SourceScale> + coord CATA_FORCEINLINE operator()( + const coord src ) { // Inbounds points are guaranteed to be inbounds after scaling up. // // e.g. point_bub_sm_ib scaled up to point_bub_ms_ib points to the top // left of the submap, which is still inbounds. - return coord_point::make_unchecked( multiply_xy( src.raw(), + return coord::make_unchecked( multiply_xy( src.raw(), ScaleUp ) ); } }; template -struct project_to_impl<0, ScaleDown, ResultScale, false> { +struct project_to_impl<0, ScaleDown, ResultScale> { template - coord_point operator()( - const coord_point &src ) { - return coord_point( + coord_point_ob CATA_FORCEINLINE operator()( + const coord_point_ob src ) { + return coord_point_ob( divide_xy_round_to_minus_infinity( src.raw(), ScaleDown ) ); } -}; -template -struct project_to_impl<0, ScaleDown, ResultScale, true> { template - coord_point operator()( - const coord_point &src ) { + coord_point_ib CATA_FORCEINLINE operator()( + const coord_point_ib src ) { // Inbounds points are guaranteed to be inbounds after scaling down. // // They are also guaranteed to be >= 0, so we can use a more effecient method of scaling. - return coord_point::make_unchecked( + return coord_point_ib::make_unchecked( divide_xy_round_to_minus_infinity_non_negative( src.raw(), ScaleDown ) ); } }; -template -inline auto project_to( const coord_point &src ) +template +CATA_FORCEINLINE auto project_to( const coord_point_ob src ) { constexpr int scale_down = map_squares_per( ResultScale ) / map_squares_per( SourceScale ); constexpr int scale_up = map_squares_per( SourceScale ) / map_squares_per( ResultScale ); - return project_to_impl()( src ); + return project_to_impl()( src ); +} + +template +CATA_FORCEINLINE auto project_to( const coord_point_ib src ) +{ + constexpr int scale_down = map_squares_per( ResultScale ) / map_squares_per( SourceScale ); + constexpr int scale_up = map_squares_per( SourceScale ) / map_squares_per( ResultScale ); + return project_to_impl()( src ); } // Resolves the remainer type for project_remain. In most cases the result shares @@ -486,27 +531,37 @@ inline auto project_to( const coord_point // do this for origin::reality_bubble template struct remainder_inbounds { - using type = coord_point; + using type = + std::conditional_t, coord_point_ob>; }; // *_sm_ms are always inbounds as remainder. template struct remainder_inbounds { - using type = coord_point; + using type = coord_point_ib; }; template using remainder_inbounds_t = typename remainder_inbounds::type; +template +using quotient_type_t = + std::conditional_t, coord_point_ob>; + template struct quotient_remainder_helper { constexpr static origin RemainderOrigin = origin_from_scale( CoarseScale ); - using quotient_type = coord_point; - using quotient_type_tripoint = coord_point; + using quotient_type = quotient_type_t; + using quotient_type_tripoint = quotient_type_t; + using quotient_type_ob = quotient_type_t; + using quotient_type_tripoint_ob = quotient_type_t; using remainder_type = remainder_inbounds_t; using remainder_type_tripoint = remainder_inbounds_t; + using remainder_type_ob = remainder_inbounds_t; + using remainder_type_tripoint_ob = + remainder_inbounds_t; }; template @@ -530,8 +585,12 @@ struct quotient_remainder_tripoint { using helper = quotient_remainder_helper; using quotient_type = typename helper::quotient_type; using quotient_type_tripoint = typename helper::quotient_type_tripoint; + using quotient_type_ob = typename helper::quotient_type_ob; + using quotient_type_tripoint_ob = typename helper::quotient_type_tripoint_ob; using remainder_type = typename helper::remainder_type; using remainder_type_tripoint = typename helper::remainder_type_tripoint; + using remainder_type_ob = typename helper::remainder_type_ob; + using remainder_type_tripoint_ob = typename helper::remainder_type_tripoint_ob; // Annoyingly, for the conversion operators below to work correctly, we // need to have point and tripoint version of both quotient and remainder @@ -555,6 +614,33 @@ struct quotient_remainder_tripoint { operator std::tuple() { return std::tie( quotient, remainder_tripoint ); } + + template < typename quotient_tripoint_ob = quotient_type_tripoint_ob, + std::enable_if_t < !std::is_same_v> * = nullptr > + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::tuple() { + return std::tie( static_cast( quotient_tripoint ), remainder ); + } + template < typename quotient_ob = quotient_type_ob, + std::enable_if_t < !std::is_same_v> * = nullptr > + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::tuple() { + return std::tie( static_cast( quotient ), remainder_tripoint ); + } + + template < typename remainder_ob = remainder_type_ob, + std::enable_if_t < !std::is_same_v> * = nullptr > + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::tuple() { + return std::tie( quotient_tripoint, static_cast( remainder ) ); + } + template < typename remainder_tripoint_ob = remainder_type_tripoint_ob, + std::enable_if_t < !std::is_same_v> * = nullptr > + // NOLINTNEXTLINE(google-explicit-constructor) + operator std::tuple() { + return std::tie( quotient, static_cast( remainder_tripoint ) ); + } + }; // project_remain returns a helper struct, intended to be used with std::tie @@ -576,9 +662,10 @@ struct quotient_remainder_tripoint { // point_abs_om quotient; // tripoint_om_sm remainder; // std::tie( quotient, remainder ) = project_remain( val ); -template -inline quotient_remainder_point project_remain( - const coord_point &src ) +template class coord, bool InBounds = coord::is_inbounds> +CATA_FORCEINLINE quotient_remainder_point +project_remain( + const coord src ) { constexpr int ScaleDown = map_squares_per( ResultScale ) / map_squares_per( SourceScale ); static_assert( ScaleDown > 0, "You can only project to coarser coordinate systems" ); @@ -591,9 +678,10 @@ inline quotient_remainder_point proj return { quotient, remainder }; } -template -inline quotient_remainder_tripoint project_remain( - const coord_point &src ) +template class coord, bool InBounds = coord::is_inbounds> +CATA_FORCEINLINE quotient_remainder_tripoint +project_remain( + const coord src ) { using qrp = quotient_remainder_tripoint; using quotient_type_tripoint = typename qrp::quotient_type_tripoint; @@ -606,44 +694,55 @@ inline quotient_remainder_tripoint p } template + origin FineOrigin, scale FineScale> inline auto project_combine( - const coord_point &coarse, - const coord_point &fine ) + const coord_point_ob &coarse, + const coord_point_ob &fine ) { static_assert( origin_from_scale( CoarseScale ) == FineOrigin, "given point types are not compatible for combination" ); static_assert( PointL::dimension != 3 || PointR::dimension != 3, "two tripoints should not be combined; it's unclear how to handle z" ); using PointResult = decltype( PointL() + PointR() ); - const coord_point refined_coarse = + const coord_point_ob refined_coarse = project_to( coarse ); - return coord_point < PointResult, CoarseOrigin, FineScale, CoarseInBounds && - FineInBounds >::make_unchecked( refined_coarse.raw() + fine.raw() ); + return coord_point < PointResult, CoarseOrigin, FineScale >::make_unchecked( + refined_coarse.raw() + fine.raw() ); } -template -inline auto project_bounds( const coord_point &coarse ) +template +inline auto project_combine( + const coord_point_ib &coarse, + const coord_point_ib &fine ) +{ + using PointResult = decltype( PointL() + PointR() ); + return coord_point_ib::make_unchecked( project_combine( + coarse.as_ob(), fine.as_ob() ).raw() ); +} + +template +inline auto project_bounds( const coord_point_ob &coarse ) { constexpr point one( 1, 1 ); // NOLINT(cata-use-named-point-constants) - return half_open_rectangle>( + return half_open_rectangle>( project_to( coarse ), project_to( coarse + one ) ); } -template -inline auto project_bounds( const coord_point &coarse ) +template +inline auto project_bounds( const coord_point_ob &coarse ) { constexpr point one( 1, 1 ); // NOLINT(cata-use-named-point-constants) - return half_open_cuboid>( + return half_open_cuboid>( project_to( coarse ), project_to( coarse + one ) ); } } // namespace coords -template +template // NOLINTNEXTLINE(cert-dcl58-cpp) -struct std::hash> { - std::size_t operator()( const coords::coord_point &p ) const { +struct std::hash> { + std::size_t operator()( const coords::coord_point_ob &p ) const { const hash h{}; return h( p.raw() ); } @@ -676,89 +775,127 @@ point_bub_ms rebase_bub( point_omt_ms p ); tripoint_bub_ms rebase_bub( tripoint_omt_ms p ); tripoint_omt_ms rebase_omt( tripoint_bub_ms p ); -template -inline int square_dist( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template +inline int square_dist( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) { return square_dist( loc1.raw(), loc2.raw() ); } -template -inline int trig_dist( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template +inline int trig_dist( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) { return trig_dist( loc1.raw(), loc2.raw() ); } -template -inline int rl_dist( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template +inline int rl_dist( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) { return rl_dist( loc1.raw(), loc2.raw() ); } -template -inline int manhattan_dist( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template +inline int manhattan_dist( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) { return manhattan_dist( loc1.raw(), loc2.raw() ); } -template -inline int octile_dist( const coords::coord_point &loc1, - const coords::coord_point &loc2, int multiplier = 1 ) +template +inline int octile_dist( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2, int multiplier = 1 ) { return octile_dist( loc1.raw(), loc2.raw(), multiplier ); } -template -direction direction_from( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template +direction direction_from( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) { return direction_from( loc1.raw(), loc2.raw() ); } -template, int> = 0> -std::vector < coords::coord_point < Point, Origin, Scale, LhsInBounds && RhsInBounds >> - line_to( const coords::coord_point &loc1, - const coords::coord_point &loc2, +template, int> = 0> +std::vector < coords::coord_point < Point, Origin, Scale >> + line_to( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2, const int t = 0 ) { std::vector raw_result = line_to( loc1.raw(), loc2.raw(), t ); - std::vector < coords::coord_point < Point, Origin, Scale, LhsInBounds &&RhsInBounds >> result; + std::vector < coords::coord_point < Point, Origin, Scale >> result; std::transform( raw_result.begin(), raw_result.end(), std::back_inserter( result ), []( const Point & p ) { - return coords::coord_point < Point, Origin, Scale, LhsInBounds && - RhsInBounds >::make_unchecked( p ); + return coords::coord_point < Point, Origin, Scale >::make_unchecked( p ); } ); return result; } -template, int> = 0> +std::vector < coords::coord_point_ib < Point, Origin, Scale >> + line_to( const coords::coord_point_ib &loc1, + const coords::coord_point_ib &loc2, + const int t = 0 ) +{ + std::vector raw_result = line_to( loc1.raw(), loc2.raw(), t ); + std::vector < coords::coord_point_ib < Point, Origin, Scale >> result; + std::transform( raw_result.begin(), raw_result.end(), std::back_inserter( result ), + []( const Point & p ) { + return coords::coord_point_ib < Point, Origin, Scale >::make_unchecked( p ); + } ); + return result; +} + +template, int> = 0> -std::vector < coords::coord_point < Tripoint, Origin, Scale, LhsInBounds && RhsInBounds >> - line_to( const coords::coord_point &loc1, - const coords::coord_point &loc2, +std::vector < coords::coord_point < Tripoint, Origin, Scale >> + line_to( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2, const int t = 0, const int t2 = 0 ) { std::vector raw_result = line_to( loc1.raw(), loc2.raw(), t, t2 ); - std::vector < coords::coord_point < Tripoint, Origin, Scale, LhsInBounds &&RhsInBounds >> result; + std::vector < coords::coord_point < Tripoint, Origin, Scale>> result; std::transform( raw_result.begin(), raw_result.end(), std::back_inserter( result ), []( const Tripoint & p ) { - return coords::coord_point < Tripoint, Origin, Scale, LhsInBounds && - RhsInBounds >::make_unchecked( p ); + return coords::coord_point < Tripoint, Origin, Scale >::make_unchecked( p ); } ); return result; } -template -coords::coord_point < Point, Origin, Scale, LhsInBounds &&RhsInBounds > -midpoint( const coords::coord_point &loc1, - const coords::coord_point &loc2 ) +template, int> = 0> +std::vector < coords::coord_point_ib < Tripoint, Origin, Scale>> + line_to( const coords::coord_point_ib &loc1, + const coords::coord_point_ib &loc2, + const int t = 0, const int t2 = 0 ) { - return coords::coord_point < Point, Origin, Scale, LhsInBounds && - RhsInBounds >::make_unchecked( ( loc1.raw() + loc2.raw() ) / 2 ); + std::vector raw_result = line_to( loc1.raw(), loc2.raw(), t, t2 ); + std::vector < coords::coord_point_ib < Tripoint, Origin, Scale >> result; + std::transform( raw_result.begin(), raw_result.end(), std::back_inserter( result ), + []( const Tripoint & p ) { + return coords::coord_point_ib < Tripoint, Origin, Scale >::make_unchecked( p ); + } ); + return result; +} + + +template +coords::coord_point < Point, Origin, Scale > +midpoint( const coords::coord_point_ob &loc1, + const coords::coord_point_ob &loc2 ) +{ + return coords::coord_point < Point, Origin, Scale >::make_unchecked( ( + loc1.raw() + loc2.raw() ) / 2 ); +} + +template +coords::coord_point_ib < Point, Origin, Scale > +midpoint( const coords::coord_point_ib &loc1, + const coords::coord_point_ib &loc2 ) +{ + return coords::coord_point_ib < Point, Origin, Scale >::make_unchecked( ( + loc1.raw() + loc2.raw() ) / 2 ); } template @@ -788,22 +925,30 @@ Tripoint midpoint( const half_open_cuboid &box ) } template -std::vector> - closest_points_first( const coords::coord_point &loc, +std::vector> + closest_points_first( const coords::coord_point_ob &loc, int min_dist, int max_dist ) { std::vector raw_result = closest_points_first( loc.raw(), min_dist, max_dist ); - std::vector> result; + std::vector> result; result.reserve( raw_result.size() ); std::transform( raw_result.begin(), raw_result.end(), std::back_inserter( result ), []( const Point & p ) { - return coords::coord_point( p ); + return coords::coord_point_ob( p ); } ); return result; } -template -std::vector> - closest_points_first( const coords::coord_point &loc, +template +std::vector> + closest_points_first( const coords::coord_point_ob &loc, + int max_dist ) +{ + return closest_points_first( loc, 0, max_dist ); +} + +template +std::vector> + closest_points_first( const coords::coord_point_ib &loc, int max_dist ) { return closest_points_first( loc, 0, max_dist ); diff --git a/src/coords_fwd.h b/src/coords_fwd.h index d8eaac37f43ca..ad73515b41042 100644 --- a/src/coords_fwd.h +++ b/src/coords_fwd.h @@ -2,6 +2,8 @@ #ifndef CATA_SRC_COORDS_FWD_H #define CATA_SRC_COORDS_FWD_H +#include + struct point; struct tripoint; @@ -32,8 +34,15 @@ constexpr scale omt = scale::overmap_terrain; constexpr scale seg = scale::segment; constexpr scale om = scale::overmap; +template +class coord_point_ob; + +template +class coord_point_ib; + template -class coord_point; +using coord_point = + std::conditional_t, coord_point_ob>; } // namespace coords @@ -76,7 +85,7 @@ using point_abs_om = coords::coord_point using tripoint_rel_ms = coords::coord_point; using tripoint_abs_ms = coords::coord_point; using tripoint_sm_ms = coords::coord_point; -using tripoint_sm_ms_ib = coords::coord_point; +using tripoint_sm_ms_ib = coords::coord_point_ib; using tripoint_omt_ms = coords::coord_point; using tripoint_bub_ms = coords::coord_point; using tripoint_bub_ms_ib = diff --git a/src/map.cpp b/src/map.cpp index d74a970ba2ced..0700b7e67a774 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1805,7 +1805,7 @@ furn_id map::furn( const tripoint &p ) const return furn( tripoint_bub_ms( p ) ); } -furn_id map::furn( const tripoint_bub_ms &p ) const +furn_id map::furn( const tripoint_bub_ms p ) const { if( !inbounds( p ) ) { return furn_str_id::NULL_ID(); @@ -2000,7 +2000,7 @@ std::string map::furnname( const tripoint_bub_ms &p ) * retained for high performance comparisons, save/load, and gradual transition * to string terrain.id */ -ter_id map::ter( const tripoint &p ) const +ter_id map::ter( const tripoint p ) const { if( !inbounds( p ) ) { return ter_str_id::NULL_ID().id(); diff --git a/src/map.h b/src/map.h index 9f98b2c384f71..d804021569ba5 100644 --- a/src/map.h +++ b/src/map.h @@ -965,7 +965,7 @@ class map } // TODO: fix point types (remove the first overload) furn_id furn( const tripoint &p ) const; - furn_id furn( const tripoint_bub_ms &p ) const; + furn_id furn( tripoint_bub_ms p ) const; // TODO: Get rid of untyped overload. furn_id furn( const point_bub_ms &p ) const { return furn( tripoint_bub_ms( p, abs_sub.z() ) ); @@ -1010,7 +1010,7 @@ class map // Terrain // TODO: fix point types (remove the first overload) - ter_id ter( const tripoint &p ) const; + ter_id ter( tripoint p ) const; ter_id ter( const tripoint_bub_ms &p ) const; // TODO: Get rid of untyped overload. ter_id ter( const point &p ) const { @@ -2399,11 +2399,9 @@ class map offset_p.y = p.y % SEEY; return unsafe_get_submap_at( p ); } - submap *unsafe_get_submap_at( const tripoint_bub_ms &p, point_sm_ms &offset_p ) { + submap *unsafe_get_submap_at( const tripoint_bub_ms p, point_sm_ms &offset_p ) { tripoint_bub_sm sm; - point_sm_ms_ib l; - std::tie( sm, l ) = project_remain( p ); - offset_p = point_sm_ms( l ); + std::tie( sm, offset_p ) = project_remain( p ); return unsafe_get_submap_at( p ); } // TODO: fix point types (remove the first overload) @@ -2413,11 +2411,9 @@ class map return unsafe_get_submap_at( p ); } const submap *unsafe_get_submap_at( - const tripoint_bub_ms &p, point_sm_ms &offset_p ) const { + const tripoint_bub_ms p, point_sm_ms &offset_p ) const { tripoint_bub_sm sm; - point_sm_ms_ib l; - std::tie( sm, l ) = project_remain( p ); - offset_p = point_sm_ms( l ); + std::tie( sm, offset_p ) = project_remain( p ); return unsafe_get_submap_at( p ); } // TODO: Get rid of untyped overload diff --git a/src/mdarray.h b/src/mdarray.h index 88077b7a98305..b3c6cbd8cd75d 100644 --- a/src/mdarray.h +++ b/src/mdarray.h @@ -16,14 +16,14 @@ namespace cata template struct mdarray_default_size_impl; -template -struct mdarray_default_size_impl> { +template class coord_point, typename Point, coords::scale Scale> +struct mdarray_default_size_impl> { static constexpr size_t value = MAPSIZE_X / map_squares_per( Scale ); static_assert( MAPSIZE_X % map_squares_per( Scale ) == 0, "Scale must be smaller than map" ); }; -template -struct mdarray_default_size_impl> { +template class coord_point, typename Point, coords::origin Origin, coords::scale Scale> +struct mdarray_default_size_impl> { static constexpr coords::scale outer_scale = coords::scale_from_origin( Origin ); static constexpr size_t value = map_squares_per( outer_scale ) / map_squares_per( Scale ); static_assert( value > 0, "Scale must be smaller origin" ); diff --git a/src/omdata.h b/src/omdata.h index f86655f9018c1..2ec8587849a8a 100644 --- a/src/omdata.h +++ b/src/omdata.h @@ -77,7 +77,7 @@ std::string name( type dir ); point rotate( const point &p, type dir ); tripoint rotate( const tripoint &p, type dir ); template -auto rotate( const coords::coord_point &p, type dir ) +auto rotate( const coords::coord_point_ob &p, type dir ) -> coords::coord_point { return coords::coord_point { rotate( p.raw(), dir ) }; diff --git a/tests/coordinate_test.cpp b/tests/coordinate_test.cpp index 1717a5d45765f..b1233cd6712af 100644 --- a/tests/coordinate_test.cpp +++ b/tests/coordinate_test.cpp @@ -18,13 +18,12 @@ static_assert( tripoint_abs_omt::dimension == 3 ); // Out of bounds coords can be implicitly constructed from inbounds ones. This is used // to ensure a return type is NOT an inbounds one, before it can be converted. -template -coords::coord_point assert_not_ib( const - coords::coord_point &p ) -{ - static_assert( !InBounds ); - return p; -} +#define assert_not_ib(p) \ + (([](auto&& _p) { \ + using _t = decltype(_p); \ + static_assert(!std::decay_t<_t>::is_inbounds); \ + return std::forward<_t>(_p); } \ + )(p)) TEST_CASE( "coordinate_strings", "[point][coords][nogame]" ) {