Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 22 additions & 34 deletions include/boost/gil/concepts/point.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright 2005-2007 Adobe Systems Incorporated
// Copyright 2026 Samuel Debionne
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
Expand All @@ -8,9 +9,13 @@
#ifndef BOOST_GIL_CONCEPTS_POINT_HPP
#define BOOST_GIL_CONCEPTS_POINT_HPP

#include <boost/gil/concepts/basic.hpp>
#include <boost/gil/concepts/concept_check.hpp>
#include <boost/gil/detail/config.hpp>

#if !defined(BOOST_GIL_HAS_CONCEPTS)
# error C++ 20 standard required.
#endif

#include <concepts>
#include <cstddef>

#if defined(BOOST_CLANG)
Expand All @@ -27,7 +32,7 @@
namespace boost { namespace gil {

// Forward declarations
template <typename T>
template <BOOST_GIL_CONSTRAINT(std::regular) T>
class point;

template <std::size_t K, typename T>
Expand Down Expand Up @@ -58,33 +63,21 @@ T& axis_value(point<T>& p);
/// \ingroup PointConcept
///
template <typename P>
struct PointNDConcept
concept PointNDConcept = requires(P point, typename P::template axis<0>::coord_t ft, typename P::template axis<P::num_dimensions - 1>::coord_t lt)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concept should be lower case?

{
void constraints()
{
gil_function_requires<Regular<P>>();

using value_type = typename P::value_type;
ignore_unused_variable_warning(value_type{});

static const std::size_t N = P::num_dimensions;
ignore_unused_variable_warning(N);
using FT = typename P::template axis<0>::coord_t;
using LT = typename P::template axis<N - 1>::coord_t;
FT ft = gil::axis_value<0>(point);
axis_value<0>(point) = ft;
LT lt = axis_value<N - 1>(point);
axis_value<N - 1>(point) = lt;

//value_type v=point[0];
//ignore_unused_variable_warning(v);
}
P point;
typename P::value_type;
requires std::regular<typename P::value_type>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better write with concept conjunctions?

concept PointNDConcept = std::regular<typename P::value_type> && requires(P point, typename...


P::num_dimensions;
ft = gil::axis_value<0>(point);
axis_value<0>(point) = ft;
lt = axis_value<P::num_dimensions - 1>(point);
axis_value<P::num_dimensions - 1>(point) = lt;
};

/// \brief 2-dimensional point concept
/// \code
/// concept Point2DConcept<typename T> : PointNDConcept<T>
/// concept Point2DConcept<typename T> : PointNDConcept<T>N
/// {
/// where num_dimensions == 2;
/// where SameType<axis<0>::type, axis<1>::type>;
Expand All @@ -100,16 +93,11 @@ struct PointNDConcept
/// \ingroup PointConcept
///
template <typename P>
struct Point2DConcept
concept Point2DConcept = PointNDConcept<P> && requires(P point)
{
void constraints()
{
gil_function_requires<PointNDConcept<P>>();
static_assert(P::num_dimensions == 2, "");
point.x = point.y;
point[0] = point[1];
}
P point;
requires P::num_dimensions == 2;
point.x = point.y;
point[0] = point[1];
};

}} // namespace boost::gil
Expand Down
23 changes: 23 additions & 0 deletions include/boost/gil/detail/config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Copyright 2026 Samuel Debionne
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_DETAIL_CONFIG_HPP
#define BOOST_GIL_DETAIL_CONFIG_HPP

#include <boost/config.hpp>

#if !defined(BOOST_NO_CXX20_HDR_CONCEPTS) && defined(__cpp_lib_concepts)
#define BOOST_GIL_HAS_CONCEPTS
#endif

#ifdef BOOST_GIL_HAS_CONCEPTS
#define BOOST_GIL_CONSTRAINT(C) C
#else
#define BOOST_GIL_CONSTRAINT(C) typename
#endif

#endif
3 changes: 3 additions & 0 deletions include/boost/gil/detail/std_common_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ struct std_common_type
>::type;
};

template <typename T, typename U>
using std_common_type_t = std_common_type<T, U>::type;

}}} // namespace boost::gil::detail

#endif
2 changes: 1 addition & 1 deletion include/boost/gil/locator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ template <typename P> std::ptrdiff_t memunit_step(const P*);
template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
template <typename P> P& memunit_advanced_ref(P* p, std::ptrdiff_t diff);
template <typename Iterator, typename D> struct iterator_add_deref;
template <typename T> class point;
template <BOOST_GIL_CONSTRAINT(std::regular) T> class point;
namespace detail {
// helper class specialized for each axis of pixel_2d_locator
template <std::size_t D, typename Loc> class locator_axis;
Expand Down
25 changes: 14 additions & 11 deletions include/boost/gil/point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
#define BOOST_GIL_POINT_HPP

#include <boost/gil/utilities.hpp>
#include <boost/gil/detail/config.hpp>
#include <boost/gil/detail/std_common_type.hpp>

#include <boost/config.hpp>

#include <cstddef>
#include <concepts>
#include <type_traits>

namespace boost { namespace gil {
Expand All @@ -31,7 +31,7 @@ namespace boost { namespace gil {
/// \brief 2D point both axes of which have the same dimension type
/// \ingroup PointModel
/// Models: Point2DConcept
template <typename T>
template <BOOST_GIL_CONSTRAINT(std::regular) T>
class point
{
public:
Expand Down Expand Up @@ -109,62 +109,65 @@ class point
};

/// Alias template for backward compatibility with Boost <=1.68.
template <typename T>
template <std::regular T>
using point2 = point<T>;

/// Common type to represent 2D dimensions or in-memory size of image or view.
/// @todo TODO: rename to dims_t or dimensions_t for purpose clarity?
using point_t = point<std::ptrdiff_t>;

template <typename T>
template <std::regular T>
T point<T>::* const point<T>::mem_array[point<T>::num_dimensions] =
{
&point<T>::x,
&point<T>::y
};

/// \ingroup PointModel
template <typename T>
template <std::regular T>
BOOST_FORCEINLINE
bool operator==(const point<T>& p1, const point<T>& p2)
{
return p1.x == p2.x && p1.y == p2.y;
}

/// \ingroup PointModel
template <typename T>
template <std::regular T>
BOOST_FORCEINLINE
bool operator!=(const point<T>& p1, const point<T>& p2)
{
return p1.x != p2.x || p1.y != p2.y;
}

/// \ingroup PointModel
template <typename T>
template <std::regular T>
BOOST_FORCEINLINE
point<T> operator+(const point<T>& p1, const point<T>& p2)
{
return { p1.x + p2.x, p1.y + p2.y };
}

/// \ingroup PointModel
template <typename T>
template <std::regular T>
BOOST_FORCEINLINE
point<T> operator-(const point<T>& p)
{
return { -p.x, -p.y };
}

/// \ingroup PointModel
template <typename T>
template <std::regular T>
BOOST_FORCEINLINE
point<T> operator-(const point<T>& p1, const point<T>& p2)
{
return { p1.x - p2.x, p1.y - p2.y };
}

template <typename T>
concept arithmetic = std::is_arithmetic_v<T>;

/// \ingroup PointModel
template <typename T, typename D>
template <std::regular T, arithmetic D>
BOOST_FORCEINLINE
auto operator/(point<T> const& p, D d)
-> typename std::enable_if
Expand Down
58 changes: 42 additions & 16 deletions include/boost/gil/typedefs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef BOOST_GIL_TYPEDEFS_HPP
#define BOOST_GIL_TYPEDEFS_HPP

#include <boost/gil/detail/config.hpp>

#include <boost/gil/cmyk.hpp>
#include <boost/gil/device_n.hpp>
#include <boost/gil/gray.hpp>
Expand All @@ -22,25 +24,49 @@
# include <memory_resource>
#endif //!defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)

namespace boost { namespace gil {

#if defined(BOOST_GIL_HAS_CONCEPTS)
template <typename, typename>
struct pixel;
template <typename, typename>
struct planar_pixel_reference;
template <typename, typename>
struct planar_pixel_iterator;
template <typename>
class memory_based_step_iterator;
template <std::regular>
class point;
template <typename>
class memory_based_2d_locator;
template <typename>
class image_view;
template <typename, bool, typename>
class image;
#else
template <typename, typename>
struct pixel;
template <typename, typename>
struct planar_pixel_reference;
template <typename, typename>
struct planar_pixel_iterator;
template <typename>
class memory_based_step_iterator;
template <typename>
class point;
template <typename>
class memory_based_2d_locator;
template <typename>
class image_view;
template <typename, bool, typename>
class image;
#endif //defined(BOOST_GIL_HAS_CONCEPTS)

}} // namespace boost::gil

// B - bits size/signedness, CM - channel model, CS - colour space, LAYOUT - pixel layout
// Example: B = '8', CM = 'uint8_t', CS = 'bgr, LAYOUT='bgr_layout_t'
#define BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
template <typename, typename> \
struct pixel; \
template <typename, typename> \
struct planar_pixel_reference; \
template <typename, typename> \
struct planar_pixel_iterator; \
template <typename> \
class memory_based_step_iterator; \
template <typename> \
class point; \
template <typename> \
class memory_based_2d_locator; \
template <typename> \
class image_view; \
template <typename, bool, typename> \
class image; \
using CS##B##_pixel_t = pixel<CM, LAYOUT>; \
using CS##B##c_pixel_t = pixel<CM, LAYOUT> const; \
using CS##B##_ref_t = pixel<CM, LAYOUT>&; \
Expand Down
13 changes: 4 additions & 9 deletions test/core/point/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,14 @@ void test_members()

int main()
{
boost::function_requires<gil::PointNDConcept<gil::point<int>>>();
boost::function_requires<gil::PointNDConcept<gil::point_t>>();
static_assert(gil::PointNDConcept<gil::point<int>>);
static_assert(gil::PointNDConcept<gil::point_t>);

boost::function_requires<gil::Point2DConcept<gil::point<int>>>();
boost::function_requires<gil::Point2DConcept<gil::point_t>>();
static_assert(gil::Point2DConcept<gil::point<int>>);
static_assert(gil::Point2DConcept<gil::point_t>);

test_members<gil::point<int>>();
test_members<gil::point_t>();

// NOTE: point2 is deprecated, available for backward compatibility
boost::function_requires<gil::PointNDConcept<gil::point2<int>>>();
boost::function_requires<gil::Point2DConcept<gil::point2<int>>>();
test_members<gil::point2<int>>();

return 0;
}
Loading