From bdedbc2a46e1655910144541fc489d232bd3931a Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Mon, 16 Oct 2023 11:48:11 -0600 Subject: [PATCH] Make ArrayView constructors more generic. --- include/deal.II/base/array_view.h | 215 +++++++++++++----------------- 1 file changed, 90 insertions(+), 125 deletions(-) diff --git a/include/deal.II/base/array_view.h b/include/deal.II/base/array_view.h index 7bf75706c5..c773259e01 100644 --- a/include/deal.II/base/array_view.h +++ b/include/deal.II/base/array_view.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -150,75 +151,112 @@ public: */ explicit ArrayView(value_type &element); +#ifdef DEAL_II_HAVE_CXX20 /** - * A constructor that automatically creates a view from a std::vector object. - * The view encompasses all elements of the given vector. + * A constructor that automatically creates a view from a container + * object that requires a contiguous array of elements (such as + * `std::vector`, `std::array`, `boost::container::small_vector`, + * and the like). The view encompasses all elements of the given + * container. * * This implicit conversion constructor is particularly useful when calling * a function that takes an ArrayView object as argument, and passing in - * a std::vector. + * a container. * - * @note This constructor takes a reference to a @p const vector as argument. + * @note This constructor takes a reference to a @p const container as argument. * It can only be used to initialize ArrayView objects that point to * @p const memory locations, such as ArrayView@. * You cannot initialize ArrayView objects to non-@p const memory with * such arguments, such as ArrayView@. */ - ArrayView(const std::vector> &vector); + template + ArrayView(const ContiguousContainer &container) + requires(std::is_same_v< + std::remove_cv_t, + std::remove_cv_t> && + std::is_const_v && + concepts::is_contiguous_container); /** - * A constructor that automatically creates a view from a std::vector object. - * The view encompasses all elements of the given vector. + * A constructor that automatically creates a view from a container + * object that requires a contiguous array of elements (such as + * `std::vector`, `std::array`, `boost::container::small_vector`, + * and the like). The view encompasses all elements of the given + * container. * * This implicit conversion constructor is particularly useful when calling * a function that takes an ArrayView object as argument, and passing in - * a std::vector. + * a container. * - * @note This constructor takes a reference to a non-@p const vector as + * @note This constructor takes a reference to a non-@p const container as * argument. It can be used to initialize ArrayView objects that point to * either @p const memory locations, such as * ArrayView@, or to non-@p const memory, * such as ArrayView@. */ - ArrayView(std::vector> &vector); + template + ArrayView(ContiguousContainer &container) + requires(std::is_same_v< + std::remove_cv_t, + std::remove_cv_t> && + concepts::is_contiguous_container); + +#else + /** - * A constructor that automatically creates a view from a - * boost::container::small_vector object. The view encompasses all elements of - * the given vector. + * A constructor that automatically creates a view from a container + * object that requires a contiguous array of elements (such as + * `std::vector`, `std::array`, `boost::container::small_vector`, + * and the like). The view encompasses all elements of the given + * container. * * This implicit conversion constructor is particularly useful when calling * a function that takes an ArrayView object as argument, and passing in - * a boost::container::small_vector. + * a container. * - * @note This constructor takes a reference to a @p const vector as argument. + * @note This constructor takes a reference to a @p const container as argument. * It can only be used to initialize ArrayView objects that point to * @p const memory locations, such as ArrayView@. * You cannot initialize ArrayView objects to non-@p const memory with * such arguments, such as ArrayView@. */ - template - ArrayView(const boost::container::small_vector, - N> &vector); + template ())), + typename = decltype(std::size(std::declval())), + typename = std::enable_if_t< + std::is_same_v< + std::remove_cv_t, + std::remove_cv_t> && + std::is_const_v>> + ArrayView(const ContiguousContainer &container); /** - * A constructor that automatically creates a view from a - * boost::container::small_vector object. The view encompasses all elements of - * the given vector. + * A constructor that automatically creates a view from a container + * object that requires a contiguous array of elements (such as + * `std::vector`, `std::array`, `boost::container::small_vector`, + * and the like). The view encompasses all elements of the given + * container. * * This implicit conversion constructor is particularly useful when calling * a function that takes an ArrayView object as argument, and passing in - * a boost::container::small_vector. + * a container. * - * @note This constructor takes a reference to a non-@p const vector as + * @note This constructor takes a reference to a non-@p const container as * argument. It can be used to initialize ArrayView objects that point to * either @p const memory locations, such as * ArrayView@, or to non-@p const memory, * such as ArrayView@. */ - template - ArrayView( - boost::container::small_vector, N> &vector); + template ())), + typename = decltype(std::size(std::declval())), + typename = std::enable_if_t, + std::remove_cv_t>>> + ArrayView(ContiguousContainer &container); + +#endif /** * A constructor that automatically creates a view for a given C-style array. @@ -237,28 +275,6 @@ public: template ArrayView(value_type (&array)[N]); - /** - * A constructor that automatically creates a view from a std::array object. - * The view encompasses all elements of the given vector. - * - * This implicit conversion constructor is particularly useful when calling - * a function that takes an ArrayView object as argument, and passing in - * a std::array. - */ - template - ArrayView(const std::array, N> &vector); - - /** - * A constructor that automatically creates a view from a std::array object. - * The view encompasses all elements of the given vector. - * - * This implicit conversion constructor is particularly useful when calling - * a function that takes an ArrayView object as argument, and passing in - * a std::array. - */ - template - ArrayView(std::array, N> &vector); - /** * A constructor that creates a view of the array that underlies a * [std::initializer_list](https://en.cppreference.com/w/cpp/utility/initializer_list). @@ -535,97 +551,57 @@ inline ArrayView::ArrayView( {} +#ifdef DEAL_II_HAVE_CXX20 template +template inline ArrayView::ArrayView( - const std::vector> &vector) + const ContiguousContainer &container) + requires(std::is_same_v< + std::remove_cv_t, + std::remove_cv_t> && + std::is_const_v && + concepts::is_contiguous_container) : // use delegating constructor - ArrayView(vector.data(), vector.size()) -{ - // the following static_assert is not strictly necessary because, - // if we got a const std::vector reference argument but ElementType - // is not itself const, then the call to the forwarding constructor - // above will already have failed: vector.data() will have returned - // a const pointer, but we need a non-const pointer. - // - // nevertheless, leave the static_assert in since it provides a - // more descriptive error message that will simply come after the first - // error produced above - static_assert(std::is_const_v == true, - "This constructor may only be called if the ArrayView " - "object has a const value_type. In other words, you can " - "only create an ArrayView to const values from a const " - "std::vector."); -} + ArrayView(container.data(), container.size()) +{} template +template inline ArrayView::ArrayView( - std::vector> &vector) + ContiguousContainer &container) + requires(std::is_same_v< + std::remove_cv_t, + std::remove_cv_t> && + concepts::is_contiguous_container) : // use delegating constructor - ArrayView(vector.data(), vector.size()) + ArrayView(std::data(container), std::size(container)) {} +#else template -template +template inline ArrayView::ArrayView( - const boost::container::small_vector, N> &vector) + const ContiguousContainer &container) : // use delegating constructor - ArrayView(vector.data(), vector.size()) -{ - // the following static_assert is not strictly necessary because, - // if we got a const boost::container::small_vector reference argument but - // ElementType is not itself const, then the call to the forwarding - // constructor above will already have failed: vector.data() will have - // returned a const pointer, but we need a non-const pointer. - // - // nevertheless, leave the static_assert in since it provides a - // more descriptive error message that will simply come after the first - // error produced above - static_assert(std::is_const_v == true, - "This constructor may only be called if the ArrayView " - "object has a const value_type. In other words, you can " - "only create an ArrayView to const values from a const " - "std::vector."); -} + ArrayView(container.data(), container.size()) +{} template -template +template inline ArrayView::ArrayView( - boost::container::small_vector, N> &vector) + ContiguousContainer &container) : // use delegating constructor - ArrayView(vector.data(), vector.size()) + ArrayView(std::data(container), std::size(container)) {} - - -template -template -inline ArrayView::ArrayView( - const std::array, N> &vector) - : // use delegating constructor - ArrayView(vector.data(), vector.size()) -{ - // the following static_assert is not strictly necessary because, - // if we got a const std::array reference argument but ElementType - // is not itself const, then the call to the forwarding constructor - // above will already have failed: vector.data() will have returned - // a const pointer, but we need a non-const pointer. - // - // nevertheless, leave the static_assert in since it provides a - // more descriptive error message that will simply come after the first - // error produced above - static_assert(std::is_const_v == true, - "This constructor may only be called if the ArrayView " - "object has a const value_type. In other words, you can " - "only create an ArrayView to const values from a const " - "std::array."); -} +#endif @@ -637,17 +613,6 @@ inline ArrayView::ArrayView( {} - -template -template -inline ArrayView::ArrayView( - std::array, N> &vector) - : // use delegating constructor - ArrayView(vector.data(), vector.size()) -{} - - - template inline ArrayView::ArrayView( const std::initializer_list> &initializer) -- 2.39.5