From ca832d9384b6af0dcaa3e277d96d4cd89f289683 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 13 May 2019 13:55:54 -0400 Subject: [PATCH] Implement first_scalar --- doc/core.qbk | 1 + doc/first_scalar.qbk | 83 ++++++++++++++++++++++++++++ include/boost/core/first_scalar.hpp | 45 +++++++++++++++ test/Jamfile.v2 | 3 + test/first_scalar_constexpr_test.cpp | 19 +++++++ test/first_scalar_test.cpp | 20 +++++++ 6 files changed, 171 insertions(+) create mode 100644 doc/first_scalar.qbk create mode 100644 include/boost/core/first_scalar.hpp create mode 100644 test/first_scalar_constexpr_test.cpp create mode 100644 test/first_scalar_test.cpp diff --git a/doc/core.qbk b/doc/core.qbk index b4f8756..0e2db2c 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -47,6 +47,7 @@ criteria for inclusion is that the utility component be: [include enable_if.qbk] [include exchange.qbk] [include explicit_operator_bool.qbk] +[include first_scalar.qbk] [include ignore_unused.qbk] [include is_same.qbk] [include lightweight_test.qbk] diff --git a/doc/first_scalar.qbk b/doc/first_scalar.qbk new file mode 100644 index 0000000..8393379 --- /dev/null +++ b/doc/first_scalar.qbk @@ -0,0 +1,83 @@ +[/ +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +] + +[section:first_scalar first_scalar] + +[simplesect Authors] + +* Glen Fernandes + +[endsimplesect] + +[section Overview] + +The header provides the function template +`boost::first_scalar` that can be used to obtain a pointer to the first scalar +element of an array. Given a pointer of type `T*` it returns a pointer of type +`remove_all_extents_t*`. + +[endsect] + +[section Examples] + +The following function uses an allocator to allocate an array of arrays and +constructs each scalar element in it. + +``` +#include +#include + +template +auto create(const A& allocator) +{ + typename std::allocator_traits::template + rebind_alloc other(allocator); + auto ptr = other.allocate(4); + try { + boost::alloc_construct_n(other, + boost::first_scalar(boost::to_address(ptr)), 24); + } catch (...) { + other.deallocate(ptr, 4); + throw; + } + return ptr; +} +``` + +[endsect] + +[section Reference] + +``` +namespace boost { + +template +constexpr T* first_scalar(T* p) noexcept; + +template +constexpr auto first_scalar(T (*p)[N]) noexcept; + +} /* boost */ +``` + +[section Functions] + +[variablelist +[[`template constexpr T* first_scalar(T* p) noexcept;`] +[[variablelist +[[Returns][`p`.]]]]] +[[`template constexpr auto first_scalar(T (*p)[N]) +noexcept;`] +[[variablelist +[[Returns][`first_scalar(&(*p)[0])`.]]]]]] + +[endsect] + +[endsect] + +[endsect] diff --git a/include/boost/core/first_scalar.hpp b/include/boost/core/first_scalar.hpp new file mode 100644 index 0000000..5373542 --- /dev/null +++ b/include/boost/core/first_scalar.hpp @@ -0,0 +1,45 @@ +/* +Copyright 2019 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_FIRST_SCALAR_HPP +#define BOOST_CORE_FIRST_SCALAR_HPP + +#include +#include + +namespace boost { +namespace detail { + +template +struct make_scalar { + typedef T type; +}; + +template +struct make_scalar { + typedef typename make_scalar::type type; +}; + +} /* detail */ + +template +BOOST_CONSTEXPR inline T* +first_scalar(T* p) BOOST_NOEXCEPT +{ + return p; +} + +template +BOOST_CONSTEXPR inline typename detail::make_scalar::type* +first_scalar(T (*p)[N]) BOOST_NOEXCEPT +{ + return boost::first_scalar(&(*p)[0]); +} + +} /* boost */ + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fc33e91..d912c1c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -127,6 +127,9 @@ run to_address_test.cpp ; run exchange_test.cpp ; run exchange_move_test.cpp ; +run first_scalar_test.cpp ; +compile first_scalar_constexpr_test.cpp ; + run empty_value_test.cpp ; run empty_value_size_test.cpp ; run empty_value_final_test.cpp ; diff --git a/test/first_scalar_constexpr_test.cpp b/test/first_scalar_constexpr_test.cpp new file mode 100644 index 0000000..e9d2500 --- /dev/null +++ b/test/first_scalar_constexpr_test.cpp @@ -0,0 +1,19 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX14_CONSTEXPR) +#include +#include + +static int i1 = 0; +BOOST_STATIC_ASSERT(boost::first_scalar(&i1) == &i1); +static int i2[4] = { }; +BOOST_STATIC_ASSERT(boost::first_scalar(i2) == &i2[0]); +static int i3[2][4][6] = { }; +BOOST_STATIC_ASSERT(boost::first_scalar(i3) == &i3[0][0][0]); +#endif diff --git a/test/first_scalar_test.cpp b/test/first_scalar_test.cpp new file mode 100644 index 0000000..3963fc8 --- /dev/null +++ b/test/first_scalar_test.cpp @@ -0,0 +1,20 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +int main() +{ + int i1 = 0; + BOOST_TEST_EQ(boost::first_scalar(&i1), &i1); + int i2[4] = { }; + BOOST_TEST_EQ(boost::first_scalar(i2), &i2[0]); + int i3[2][4][6] = { }; + BOOST_TEST_EQ(boost::first_scalar(i3), &i3[0][0][0]); + return boost::report_errors(); +}