Implement pointer_in_range

This commit is contained in:
Glen Fernandes 2024-04-08 00:25:27 -04:00
parent 083b41c17e
commit 31117ef800
6 changed files with 196 additions and 0 deletions

View File

@ -70,6 +70,7 @@ criteria for inclusion is that the utility component be:
[include null_deleter.qbk]
[include fclose_deleter.qbk]
[include nvp.qbk]
[include pointer_in_range.qbk]
[include pointer_traits.qbk]
[include quick_exit.qbk]
[include ref.qbk]

80
doc/pointer_in_range.qbk Normal file
View File

@ -0,0 +1,80 @@
[/
Copyright 2024 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
]
[section:pointer_in_range pointer_in_range]
[simplesect Authors]
* Glen Fernandes
[endsimplesect]
[section Overview]
The header <boost/core/pointer_in_range.hpp> provides the function template
`boost::pointer_in_range` to check if a pointer is in a given range. This
can be used in constant expressions in C++14 or higher when the compiler has a
builtin to support `std::is_constant_evaluated`.
[endsect]
[section Examples]
The following is an example of an allocator's deallocation function that does
nothing if the pointer falls within a small automatically allocated buffer.
```
template<class T, class N>
void
Allocator<T, N>::deallocate(pointer ptr, size_type)
{
if (!boost::pointer_in_range(ptr, &buffer_[0], &buffer_[N])) {
::operator delete(ptr);
}
}
```
[endsect]
[section Reference]
```
namespace boost {
template<class T>
constexpr bool pointer_in_range(const T* ptr, const T* begin, const T* end);
} /* boost */
```
[section Functions]
[variablelist
[[`template<class T> constexpr bool pointer_in_range(const T* ptr,
const T* begin, T* end);`]
[[variablelist
[[Returns][`true` if `ptr` is in range `[begin,end)`, otherwise `false`.]]]]]]
[endsect]
[endsect]
[section Notes]
If `boost::pointer_in_range` is not usable in constant expressions the macro
`BOOST_CORE_NO_CONSTEXPR_POINTER_IN_RANGE` is defined.
[endsect]
[section History]
Glen Fernandes implemented `pointer_in_range`.
[endsect]
[endsect]

View File

@ -0,0 +1,49 @@
/*
Copyright 2024 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_CORE_POINTER_IN_RANGE_HPP
#define BOOST_CORE_POINTER_IN_RANGE_HPP
#include <boost/config.hpp>
#include <functional>
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1925
#define BOOST_CORE_DETAIL_HAS_IS_CONSTEVAL
#elif defined(__has_builtin)
#if __has_builtin(__builtin_is_constant_evaluated)
#define BOOST_CORE_DETAIL_HAS_IS_CONSTEVAL
#endif
#endif
#endif
#if !defined(BOOST_CORE_DETAIL_HAS_IS_CONSTEVAL)
#define BOOST_CORE_NO_CONSTEXPR_POINTER_IN_RANGE
#endif
namespace boost {
template<class T>
inline BOOST_CONSTEXPR bool
pointer_in_range(const T* p, const T* b, const T* e)
{
#if defined(BOOST_CORE_DETAIL_HAS_IS_CONSTEVAL)
if ( __builtin_is_constant_evaluated()) {
for (; b != e; ++b) {
if (b == p) {
return true;
}
}
return false;
}
#endif
return std::less_equal<const T*>()(b, p) && std::less<const T*>()(p, e);
}
} /* boost */
#endif

View File

@ -416,5 +416,8 @@ run sp_thread_sleep_test.cpp ;
run yield_prim_windows_h_test.cpp ;
run yield_prim_pthread_cancel_test.cpp : ;
run pointer_in_range_test.cpp ;
compile pointer_in_range_constexpr_test.cpp ;
use-project /boost/core/swap : ./swap ;
build-project ./swap ;

View File

@ -0,0 +1,31 @@
/*
Copyright 2024 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/pointer_in_range.hpp>
#include <boost/static_assert.hpp>
#if !defined(BOOST_CORE_NO_CONSTEXPR_POINTER_IN_RANGE)
int a[4] = { 0, 0, 0, 0 };
int n = 0;
const int b[4] = { 0, 0, 0, 0 };
const int m = 0;
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&a[0], &a[1], a + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&a[1], &a[1], a + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&a[2], &a[1], a + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&a[3], &a[1], a + 4));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(a + 4, &a[1], a + 4));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&n, &a[0], &a[3]));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&m, &a[0], &a[3]));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&b[0], &b[1], b + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&b[1], &b[1], b + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&b[2], &b[1], b + 4));
BOOST_STATIC_ASSERT(boost::pointer_in_range(&b[3], &b[1], b + 4));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(b + 4, &b[1], b + 4));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&n, &b[0], &b[3]));
BOOST_STATIC_ASSERT(!boost::pointer_in_range(&m, &b[0], &b[3]));
#endif

View File

@ -0,0 +1,32 @@
/*
Copyright 2024 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/core/pointer_in_range.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
int a[4] = { 0, 0, 0, 0 };
int n = 0;
const int b[4] = { 0, 0, 0, 0 };
const int m = 0;
BOOST_TEST(!boost::pointer_in_range(&a[0], &a[1], a + 4));
BOOST_TEST(boost::pointer_in_range(&a[1], &a[1], a + 4));
BOOST_TEST(boost::pointer_in_range(&a[2], &a[1], a + 4));
BOOST_TEST(boost::pointer_in_range(&a[3], &a[1], a + 4));
BOOST_TEST(!boost::pointer_in_range(a + 4, &a[1], a + 4));
BOOST_TEST(!boost::pointer_in_range(&n, &a[0], &a[3]));
BOOST_TEST(!boost::pointer_in_range(&m, &a[0], &a[3]));
BOOST_TEST(!boost::pointer_in_range(&b[0], &b[1], b + 4));
BOOST_TEST(boost::pointer_in_range(&b[1], &b[1], b + 4));
BOOST_TEST(boost::pointer_in_range(&b[2], &b[1], b + 4));
BOOST_TEST(boost::pointer_in_range(&b[3], &b[1], b + 4));
BOOST_TEST(!boost::pointer_in_range(b + 4, &b[1], b + 4));
BOOST_TEST(!boost::pointer_in_range(&n, &b[0], &b[3]));
BOOST_TEST(!boost::pointer_in_range(&m, &b[0], &b[3]));
return boost::report_errors();
}