diff --git a/LICENSE.md b/LICENSE.md index fb04a830cf..6f5012ac35 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -134,4 +134,4 @@ associated software packages may are listed below: 10. experimental/mdspan - https://github.com/kokkos/mdspan Kokkos v. 2.0, Copyright (2019) Sandia Corporation, BSD-3 License - Git version hash: a7990884f090365787a90cdc12e689822d642c65 + Git version hash: c80a398cc84b7a2d982bfaadffd10efeab56a799 diff --git a/src/experimental/.clang-format b/src/experimental/.clang-format new file mode 100644 index 0000000000..48d374ca41 --- /dev/null +++ b/src/experimental/.clang-format @@ -0,0 +1,4 @@ +--- +Language: Cpp +DisableFormat: true +... diff --git a/src/experimental/__p0009_bits/accessor_basic.hpp b/src/experimental/__p0009_bits/accessor_basic.hpp index 864d2330bf..86895dce8b 100644 --- a/src/experimental/__p0009_bits/accessor_basic.hpp +++ b/src/experimental/__p0009_bits/accessor_basic.hpp @@ -45,20 +45,22 @@ #include "macros.hpp" -#include +#include // ptrdiff_t namespace std { namespace experimental { -template struct accessor_basic { - +template +struct accessor_basic { + using offset_policy = accessor_basic; using element_type = ElementType; - using reference = ElementType &; - using pointer = ElementType *; + using reference = ElementType&; + using pointer = ElementType*; MDSPAN_INLINE_FUNCTION - constexpr pointer offset(pointer p, ptrdiff_t i) const noexcept { + constexpr pointer + offset(pointer p, ptrdiff_t i) const noexcept { return p + i; } @@ -68,7 +70,10 @@ template struct accessor_basic { } MDSPAN_INLINE_FUNCTION - constexpr pointer decay(pointer p) const noexcept { return p; } + constexpr pointer decay(pointer p) const noexcept { + return p; + } + }; } // end namespace experimental diff --git a/src/experimental/__p0009_bits/all_type.hpp b/src/experimental/__p0009_bits/all_type.hpp index a6276c662a..6631c7e168 100644 --- a/src/experimental/__p0009_bits/all_type.hpp +++ b/src/experimental/__p0009_bits/all_type.hpp @@ -48,9 +48,9 @@ namespace std { namespace experimental { -struct all_type {}; +struct all_type { }; -_MDSPAN_INLINE_VARIABLE constexpr auto all = all_type{}; +_MDSPAN_INLINE_VARIABLE constexpr auto all = all_type{ }; } // end namespace experimental } // namespace std diff --git a/src/experimental/__p0009_bits/array_workaround.hpp b/src/experimental/__p0009_bits/array_workaround.hpp deleted file mode 100644 index 846078a859..0000000000 --- a/src/experimental/__p0009_bits/array_workaround.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* -//@HEADER -// ************************************************************************ -// -// Kokkos v. 2.0 -// Copyright (2019) Sandia Corporation -// -// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, -// the U.S. Government retains certain rights in this software. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the Corporation nor the names of the -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Questions? Contact Christian R. Trott (crtrott@sandia.gov) -// -// ************************************************************************ -//@HEADER -*/ - -#ifndef MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_ -#define MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_ - -#include "macros.hpp" -#include "trait_backports.hpp" - -#include -#include -#include - -namespace std { -namespace experimental { -// nvcc itself and icc's optimizer both don't play well with std::array :-/ -namespace __array_workaround { - -// Assumes T is integral, which works for our use case -template struct __array_entry_impl { - T __value = {}; - -#if !MDSPAN_HAS_CXX_14 - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl( - __array_entry_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl( - __array_entry_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14 __array_entry_impl & - operator=(__array_entry_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14 __array_entry_impl & - operator=(__array_entry_impl &&) noexcept = default; - MDSPAN_FORCE_INLINE_FUNCTION constexpr __array_entry_impl(T &&val) noexcept - : __value(std::move(val)) {} -#endif - MDSPAN_FORCE_INLINE_FUNCTION - constexpr T __iget(ptrdiff_t i) const noexcept { - return (i == Idx) ? __value : T(0); - } - MDSPAN_FORCE_INLINE_FUNCTION - _MDSPAN_CONSTEXPR_14 __mdspan_enable_fold_comma __iset(ptrdiff_t i, - T val) noexcept { - if (i == Idx) - __value = val; - return {}; - } -}; - -template struct __array_impl; - -template using __repeated = T; - -template -struct __array_impl> - : __array_entry_impl... { - static constexpr size_t __size = N; - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __array_impl(__array_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr __array_impl(__array_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __array_impl & - operator=(__array_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED __array_impl & - operator=(__array_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~__array_impl() noexcept = default; - - MDSPAN_FUNCTION_REQUIRES((MDSPAN_FORCE_INLINE_FUNCTION constexpr), - __array_impl, (), noexcept, - /* requires */ N != 0) - : __array_entry_impl()... {} - - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __array_impl(__repeated... vals) noexcept - : __array_entry_impl({T{vals}})... {} - - MDSPAN_FUNCTION_REQUIRES((MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr), - __array_impl, (array vals), noexcept, - /* requires */ N != 0) - : __array_entry_impl({T{vals[Idxs]}})... {} - - MDSPAN_FORCE_INLINE_FUNCTION - constexpr __array_impl(array vals) noexcept {} - - // TODO remove this, it's unused - MDSPAN_FORCE_INLINE_FUNCTION - constexpr T __get(ptrdiff_t i) const noexcept { - // For N > 0, this should work: - // (static_cast<__array_entry_impl>(this) + i)->__value; - return _MDSPAN_FOLD_PLUS_RIGHT( - (this->__array_entry_impl::__iget(i)), /* + ... + */ 0); - } - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr T const &__get_n() const noexcept { - return this->__array_entry_impl::__value; - } - - // TODO remove this, it's unused - MDSPAN_FORCE_INLINE_FUNCTION - _MDSPAN_CONSTEXPR_14 void __set(ptrdiff_t i, T val) noexcept { - _MDSPAN_FOLD_COMMA( - this->__array_entry_impl::__iset(i, val) /*, ... */); - } - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void - __set_n(T val) noexcept { - this->__array_entry_impl::__value = val; - } -}; - -template -struct __array : __array_impl> { - using base_t = __array_impl>; - using base_t::base_t; -}; - -} // end namespace __array_workaround -} // end namespace experimental -} // end namespace std - -#endif //MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_ diff --git a/src/experimental/__p0009_bits/basic_mdspan.hpp b/src/experimental/__p0009_bits/basic_mdspan.hpp index c569822901..e86a9d714a 100644 --- a/src/experimental/__p0009_bits/basic_mdspan.hpp +++ b/src/experimental/__p0009_bits/basic_mdspan.hpp @@ -41,48 +41,67 @@ //@HEADER */ + #pragma once #include "accessor_basic.hpp" -#include "extents.hpp" #include "layout_right.hpp" +#include "extents.hpp" #include "trait_backports.hpp" -#include // std::apply -#include // make_index_sequence - namespace std { namespace experimental { -template > + +template < + class ElementType, + class Extents, + class LayoutPolicy = layout_right, + class AccessorPolicy = accessor_basic +> class basic_mdspan; -template -class basic_mdspan, - LayoutPolicy, AccessorPolicy> { + +template < + class ElementType, + ptrdiff_t... Exts, + class LayoutPolicy, + class AccessorPolicy +> +class basic_mdspan< + ElementType, + std::experimental::extents, + LayoutPolicy, + AccessorPolicy +> +{ private: - // Workaround for non-deducibility of the index sequence template parameter - // if it's given at the top level - template > struct __impl; - - template struct __impl> { - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ptrdiff_t - __size(basic_mdspan const &__self) noexcept { - return _MDSPAN_FOLD_TIMES_RIGHT( - (__self.map_.extents().template __extent()), /* * ... * */ 1); + + using __mapping_base_t = detail::__no_unique_address_emulation< + typename LayoutPolicy::template mapping>, 0>; + using __accessor_base_t = detail::__no_unique_address_emulation; + + // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level + template > + struct __impl; + + template + struct __impl> + { + MDSPAN_FORCE_INLINE_FUNCTION static constexpr + ptrdiff_t __size(basic_mdspan const& __self) noexcept { + return _MDSPAN_FOLD_TIMES_RIGHT((__self.__mapping_ref().extents().template __extent()), /* * ... * */ 1); } template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ReferenceType - __callop(basic_mdspan const &__self, - const array &indices) noexcept { - return __self.acc_.access(__self.ptr_, __self.map_(indices[Idxs]...)); + MDSPAN_FORCE_INLINE_FUNCTION static constexpr + ReferenceType __callop(basic_mdspan const& __self, const array& indices) noexcept { + return __self.__accessor_ref().access(__self.__pointer_ref(), __self.__mapping_ref()(indices[Idxs]...)); } }; public: - //---------------------------------------------------------------------------- + + //-------------------------------------------------------------------------------- // Domain and codomain types using extents_type = std::experimental::extents; @@ -96,187 +115,183 @@ class basic_mdspan, using pointer = typename accessor_type::pointer; using reference = typename accessor_type::reference; - //---------------------------------------------------------------------------- +private: + + using __map_acc_pair_t = detail::__compressed_pair; + +public: + + //-------------------------------------------------------------------------------- // [mdspan.basic.cons], basic_mdspan constructors, assignment, and destructor MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan( - const basic_mdspan &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan( - basic_mdspan &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan(const basic_mdspan&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan(basic_mdspan&&) noexcept = default; // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class... IndexType, - /* requires */ ( - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, IndexType, - index_type) /* && ... */) && - (sizeof...(IndexType) == extents_type::rank_dynamic()) && - _MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) && - _MDSPAN_TRAIT(is_default_constructible, accessor_type))) + class... IndexType, + /* requires */ ( + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, IndexType, index_type) /* && ... */) && + (sizeof...(IndexType) == extents_type::rank_dynamic()) && + _MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) && + _MDSPAN_TRAIT(is_default_constructible, accessor_type) + ) + ) MDSPAN_INLINE_FUNCTION - explicit constexpr basic_mdspan(pointer p, - IndexType... dynamic_extents) noexcept - // TODO @proposal-bug shouldn't I be allowed to do `move(p)` here? - : ptr_(p), map_(extents_type(dynamic_extents...)), acc_() {} + explicit constexpr basic_mdspan(pointer p, IndexType... dynamic_extents) + noexcept + // TODO @proposal-bug shouldn't I be allowed to do `move(p)` here? + : __members(p, __map_acc_pair_t(mapping_type(extents_type(dynamic_extents...)), accessor_type())) + { } // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class IndexType, size_t N, - /* requires */ - (_MDSPAN_TRAIT(is_convertible, IndexType, index_type) && - (N == extents_type::rank_dynamic()) && - _MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) && - _MDSPAN_TRAIT(is_default_constructible, accessor_type))) + class IndexType, size_t N, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && + (N == extents_type::rank_dynamic()) && + _MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) && + _MDSPAN_TRAIT(is_default_constructible, accessor_type) + ) + ) MDSPAN_INLINE_FUNCTION - explicit constexpr basic_mdspan( - pointer p, const array &dynamic_extents) noexcept - : ptr_(p), map_(extents_type(dynamic_extents)), acc_() {} + explicit constexpr basic_mdspan(pointer p, const array& dynamic_extents) + noexcept + : __members(p, __map_acc_pair_t(mapping_type(extents_type(dynamic_extents)), accessor_type())) + { } // TODO noexcept specification MDSPAN_FUNCTION_REQUIRES( - (MDSPAN_INLINE_FUNCTION constexpr), basic_mdspan, - (pointer p, const mapping_type &m), noexcept, - /* requires */ (_MDSPAN_TRAIT(is_default_constructible, accessor_type))) - : ptr_(p), map_(m), acc_() {} + (MDSPAN_INLINE_FUNCTION constexpr), + basic_mdspan, (pointer p, const mapping_type& m), noexcept, + /* requires */ (_MDSPAN_TRAIT(is_default_constructible, accessor_type)) + ) : __members(p, __map_acc_pair_t(m, accessor_type())) + { } // TODO noexcept specification MDSPAN_INLINE_FUNCTION - constexpr basic_mdspan(pointer p, const mapping_type &m, - const accessor_type &a) noexcept - : ptr_(p), map_(m), acc_(a) {} + constexpr basic_mdspan(pointer p, const mapping_type& m, const accessor_type& a) noexcept + : __members(p, __map_acc_pair_t(m, a)) + { } // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, class OtherExtents, class OtherLayoutPolicy, - class OtherAccessor, - /* requires */ - (_MDSPAN_TRAIT(is_convertible, - typename OtherLayoutPolicy::template mapping, - mapping_type) && - _MDSPAN_TRAIT(is_convertible, OtherAccessor, accessor_type) && - _MDSPAN_TRAIT(is_convertible, typename OtherAccessor::pointer, - pointer) && - // TODO @proposal-bug there is a redundant constraint in the proposal; - // the convertibility of the extents is effectively stated twice - _MDSPAN_TRAIT(is_convertible, OtherExtents, extents_type))) + class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, typename OtherLayoutPolicy::template mapping, mapping_type) && + _MDSPAN_TRAIT(is_convertible, OtherAccessor, accessor_type) && + _MDSPAN_TRAIT(is_convertible, typename OtherAccessor::pointer, pointer) && + // TODO @proposal-bug there is a redundant constraint in the proposal; the convertibility of the extents is effectively stated twice + _MDSPAN_TRAIT(is_convertible, OtherExtents, extents_type) + ) + ) MDSPAN_INLINE_FUNCTION - constexpr basic_mdspan( - const basic_mdspan &other) - : ptr_(other.ptr_), map_(other.map_), acc_(other.acc_) {} + constexpr basic_mdspan(const basic_mdspan& other) + : __members(other.__ptr_ref(), __map_acc_pair_t(other.__mapping_ref(), other.__accessor_ref())) + { } MDSPAN_INLINE_FUNCTION_DEFAULTED ~basic_mdspan() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan & - operator=(const basic_mdspan &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan & - operator=(basic_mdspan &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan& operator=(const basic_mdspan&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan& operator=(basic_mdspan&&) noexcept = default; MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, ptrdiff_t... OtherExtents, - class OtherLayoutPolicy, class OtherAccessorPolicy, - /* requires */ - (_MDSPAN_TRAIT(is_assignable, mapping_type, - typename OtherLayoutPolicy::template mapping< - std::experimental::extents>) && - _MDSPAN_TRAIT(is_assignable, accessor_type, OtherAccessorPolicy) && - _MDSPAN_TRAIT(is_assignable, pointer, - typename OtherAccessorPolicy::pointer) && - sizeof...(OtherExtents) == extents_type::rank() && - // "For all r in the range [0, rank()), if other.static_extent(r) != dynamic_extent - // && static_extent(r) != dynamic_extent is true, then - // other.static_extent(r) == static_extent(r) is true." - // (this is just the convertiblity constraint on extents...) - _MDSPAN_TRAIT(is_convertible, std::experimental::extents, - std::experimental::extents))) + class OtherElementType, ptrdiff_t... OtherExtents, class OtherLayoutPolicy, class OtherAccessorPolicy, + /* requires */ ( + _MDSPAN_TRAIT(is_assignable, mapping_type, typename OtherLayoutPolicy::template mapping>) && + _MDSPAN_TRAIT(is_assignable, accessor_type, OtherAccessorPolicy) && + _MDSPAN_TRAIT(is_assignable, pointer, typename OtherAccessorPolicy::pointer) && + sizeof...(OtherExtents) == extents_type::rank() && + // "For all r in the range [0, rank()), if other.static_extent(r) != dynamic_extent + // && static_extent(r) != dynamic_extent is true, then + // other.static_extent(r) == static_extent(r) is true." + // (this is just the convertiblity constraint on extents...) + _MDSPAN_TRAIT(is_convertible, std::experimental::extents, std::experimental::extents) + ) + ) MDSPAN_INLINE_FUNCTION - _MDSPAN_CONSTEXPR_14 basic_mdspan & - operator=(const basic_mdspan, - OtherLayoutPolicy, OtherAccessorPolicy> - &other) noexcept(/* TODO noexcept specification */ true) { - ptr_ = other.ptr_; - map_ = other.map_; - acc_ = other.acc_; + _MDSPAN_CONSTEXPR_14 basic_mdspan& operator=( + const basic_mdspan, OtherLayoutPolicy, OtherAccessorPolicy>& other + ) noexcept(/* TODO noexcept specification */ true) + { + __ptr_ref() = other.__ptr_ref(); + __mapping_ref() = other.__mapping_ref(); + __accessor_ref() = other.__accessor_ref(); return *this; } - //---------------------------------------------------------------------------- - // [mdspan.basic.mapping], basic_mdspan mapping domain multidimensional index - // to access codomain element + //-------------------------------------------------------------------------------- + // [mdspan.basic.mapping], basic_mdspan mapping domain multidimensional index to access codomain element - MDSPAN_TEMPLATE_REQUIRES(class Index, - /* requires */ (_MDSPAN_TRAIT(is_convertible, Index, - index_type) && - sizeof...(Exts) == 1)) + MDSPAN_TEMPLATE_REQUIRES( + class Index, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, Index, index_type) && + sizeof...(Exts) == 1 + ) + ) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator[](Index idx) const noexcept { - return acc_.access(ptr_, map_(index_type(idx))); + constexpr reference operator[](Index idx) const noexcept + { + return __accessor_ref().access(__ptr_ref(), __mapping_ref()(index_type(idx))); } - MDSPAN_TEMPLATE_REQUIRES(class... IndexType, - /* requires */ (_MDSPAN_FOLD_AND(_MDSPAN_TRAIT( - is_convertible, IndexType, - index_type) /* && ... */) && - sizeof...(Exts) == - extents_type::rank())) + MDSPAN_TEMPLATE_REQUIRES( + class... IndexType, + /* requires */ ( + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, IndexType, index_type) /* && ... */) && + sizeof...(Exts) == extents_type::rank() + ) + ) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator()(IndexType... indices) const noexcept { - return acc_.access(ptr_, map_(index_type(indices)...)); + constexpr reference operator()(IndexType... indices) const noexcept + { + return __accessor_ref().access(__ptr_ref(), __mapping_ref()(index_type(indices)...)); } - MDSPAN_TEMPLATE_REQUIRES(class IndexType, size_t N, - /* requires */ - (_MDSPAN_TRAIT(is_convertible, IndexType, - index_type) && - N == extents_type::rank())) + MDSPAN_TEMPLATE_REQUIRES( + class IndexType, size_t N, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, IndexType, index_type) && + N == extents_type::rank() + ) + ) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator()(const array &indices) const - noexcept { + constexpr reference operator()(const array& indices) const noexcept + { return __impl<>::template __callop(*this, indices); } - MDSPAN_INLINE_FUNCTION - accessor_type accessor() const { return acc_; }; + // TODO @proposal-bug The proposal is missing constexpr here + MDSPAN_INLINE_FUNCTION constexpr + accessor_type accessor() const { return __accessor_ref(); }; - //---------------------------------------------------------------------------- - // [mdspan.basic.domobs], basic_mdspan observers of the domain - // multidimensional index space + //-------------------------------------------------------------------------------- + // [mdspan.basic.domobs], basic_mdspan observers of the domain multidimensional index space - MDSPAN_INLINE_FUNCTION static constexpr int rank() noexcept { - return extents_type::rank(); - } - MDSPAN_INLINE_FUNCTION static constexpr int rank_dynamic() noexcept { - return extents_type::rank_dynamic(); - } - MDSPAN_INLINE_FUNCTION static constexpr index_type - static_extent(size_t r) noexcept { - return extents_type::static_extent(r); - } + MDSPAN_INLINE_FUNCTION static constexpr int rank() noexcept { return extents_type::rank(); } + MDSPAN_INLINE_FUNCTION static constexpr int rank_dynamic() noexcept { return extents_type::rank_dynamic(); } + MDSPAN_INLINE_FUNCTION static constexpr index_type static_extent(size_t r) noexcept { return extents_type::static_extent(r); } - MDSPAN_INLINE_FUNCTION constexpr extents_type extents() const noexcept { - return map_.extents(); - }; - MDSPAN_INLINE_FUNCTION constexpr index_type extent(size_t r) const noexcept { - return map_.extents().extent(r); - }; + MDSPAN_INLINE_FUNCTION constexpr extents_type extents() const noexcept { return __mapping_ref().extents(); }; + MDSPAN_INLINE_FUNCTION constexpr index_type extent(size_t r) const noexcept { return __mapping_ref().extents().extent(r); }; MDSPAN_INLINE_FUNCTION constexpr index_type size() const noexcept { return __impl<>::__size(*this); }; - // TODO @proposal-bug for non-unique, non-contiguous mappings this is - // unimplementable - MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 index_type unique_size() const - noexcept { - if (map_.is_unique()) { + // TODO @proposal-bug for non-unique, non-contiguous mappings this is unimplementable + MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 index_type unique_size() const noexcept { + if(__mapping_ref().is_unique()) { return size(); - } else if (map_.is_contiguous()) { - return map_.required_span_size(); - } else { + } + else if(__mapping_ref().is_contiguous()) { + return __mapping_ref().required_span_size(); + } + else { // ??? guess, for now, until this gets fixed in the proposal ??? - return map_.required_span_size(); + return __mapping_ref().required_span_size(); } } @@ -284,47 +299,38 @@ class basic_mdspan, // TODO span (or just `codomain` function, as discussed) // constexpr span span() const noexcept; - MDSPAN_INLINE_FUNCTION constexpr pointer data() const noexcept { - return ptr_; - }; + MDSPAN_INLINE_FUNCTION constexpr pointer data() const noexcept { return __ptr_ref(); }; - //---------------------------------------------------------------------------- + //-------------------------------------------------------------------------------- // [mdspan.basic.obs], basic_mdspan observers of the mapping - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { - return mapping_type::is_always_unique(); - }; - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { - return mapping_type::is_always_contiguous(); - }; - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { - return mapping_type::is_always_strided(); - }; + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return mapping_type::is_always_unique(); }; + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return mapping_type::is_always_contiguous(); }; + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return mapping_type::is_always_strided(); }; - MDSPAN_INLINE_FUNCTION constexpr mapping_type mapping() const noexcept { - return map_; - }; - MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { - return map_.is_unique(); - }; - MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { - return map_.is_contiguous(); - }; - MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { - return map_.is_strided(); - }; - MDSPAN_INLINE_FUNCTION constexpr index_type stride(size_t r) const { - return map_.stride(r); - }; + MDSPAN_INLINE_FUNCTION constexpr mapping_type mapping() const noexcept { return __mapping_ref(); }; + MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return __mapping_ref().is_unique(); }; + MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { return __mapping_ref().is_contiguous(); }; + MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return __mapping_ref().is_strided(); }; + MDSPAN_INLINE_FUNCTION constexpr index_type stride(size_t r) const { return __mapping_ref().stride(r); }; private: - pointer ptr_ = nullptr; - _MDSPAN_NO_UNIQUE_ADDRESS mapping_type map_; - _MDSPAN_NO_UNIQUE_ADDRESS accessor_type acc_; - template friend class basic_mdspan; + detail::__compressed_pair __members; + + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 pointer& __ptr_ref() noexcept { return __members.__first(); } + MDSPAN_FORCE_INLINE_FUNCTION constexpr pointer const& __ptr_ref() const noexcept { return __members.__first(); } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping_type& __mapping_ref() noexcept { return __members.__second().__first(); } + MDSPAN_FORCE_INLINE_FUNCTION constexpr mapping_type const& __mapping_ref() const noexcept { return __members.__second().__first(); } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 accessor_type& __accessor_ref() noexcept { return __members.__second().__second(); } + MDSPAN_FORCE_INLINE_FUNCTION constexpr accessor_type const& __accessor_ref() const noexcept { return __members.__second().__second(); } + + template + friend class basic_mdspan; + }; + template using mdspan = basic_mdspan>; diff --git a/src/experimental/__p0009_bits/config.hpp b/src/experimental/__p0009_bits/config.hpp index 50f366839f..aaa4a15674 100644 --- a/src/experimental/__p0009_bits/config.hpp +++ b/src/experimental/__p0009_bits/config.hpp @@ -45,14 +45,14 @@ #define _MDSPAN_INCLUDE_EXPERIMENTAL_BITS_CONFIG_HPP_ #ifndef __has_include -#define __has_include(x) 0 +# define __has_include(x) 0 #endif #if __has_include() -#include +# include #else -#include -#include +# include +# include #endif #define MDSPAN_CXX_STD_14 201402L @@ -62,123 +62,119 @@ #define MDSPAN_HAS_CXX_17 (__cplusplus >= MDSPAN_CXX_STD_17) #ifdef __apple_build_version__ -#define _MDSPAN_COMPILER_APPLECLANG +# define _MDSPAN_COMPILER_APPLECLANG #endif -#ifdef __clang_version__ -#define _MDSPAN_COMPILER_LLVMCLANG +#ifndef __has_cpp_attribute +# define __has_cpp_attribute(x) 0 #endif -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 +#ifndef _MDSPAN_PRESERVE_STANDARD_LAYOUT +// Preserve standard layout by default, but we're not removing the old version +// that turns this off until we're sure this doesn't have an unreasonable cost +// to the compiler or optimizer. +# define _MDSPAN_PRESERVE_STANDARD_LAYOUT 1 #endif #ifndef _MDSPAN_NO_UNIQUE_ADDRESS -#if __has_cpp_attribute(no_unique_address) >= 201803L -#define _MDSPAN_NO_UNIQUE_ADDRESS [[no_unique_address]] -#else -#define _MDSPAN_NO_UNIQUE_ADDRESS -#endif +# if __has_cpp_attribute(no_unique_address) >= 201803L +# define _MDSPAN_NO_UNIQUE_ADDRESS [[no_unique_address]] +# else +# define _MDSPAN_NO_UNIQUE_ADDRESS +# endif #endif #ifndef _MDSPAN_USE_CONCEPTS -#if defined(__cpp_concepts) && __cpp_concepts >= 201507L -#define _MDSPAN_USE_CONCEPTS 1 -#endif +# if defined(__cpp_concepts) && __cpp_concepts >= 201507L +# define _MDSPAN_USE_CONCEPTS 1 +# endif #endif #ifndef _MDSPAN_USE_FOLD_EXPRESSIONS -#if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) || \ - MDSPAN_HAS_CXX_17 -#define _MDSPAN_USE_FOLD_EXPRESSIONS 1 -#endif +# if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) \ + || (!defined(__cpp_fold_expressions) && MDSPAN_HAS_CXX_17) +# define _MDSPAN_USE_FOLD_EXPRESSIONS 1 +# endif #endif #ifndef _MDSPAN_USE_INLINE_VARIABLES -#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L -#define _MDSPAN_USE_INLINE_VARIABLES 1 -#endif +# if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L \ + || (!defined(__cpp_inline_variables) && MDSPAN_HAS_CXX_17) +# define _MDSPAN_USE_INLINE_VARIABLES 1 +# endif #endif #ifndef _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS -#if !(defined(__cpp_lib_type_trait_variable_templates) && \ - __cpp_lib_type_trait_variable_templates >= 201510L) && \ - !MDSPAN_HAS_CXX_17 -#define _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1 -#endif +# if !(defined(__cpp_lib_type_trait_variable_templates) && __cpp_lib_type_trait_variable_templates >= 201510L) \ + || !MDSPAN_HAS_CXX_17 +# define _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1 +# endif #endif #ifndef _MDSPAN_USE_VARIABLE_TEMPLATES -#if (defined(__cpp_variable_templates) && \ - __cpp_variable_templates >= 201304) && \ - MDSPAN_HAS_CXX_14 -#define _MDSPAN_USE_VARIABLE_TEMPLATES 1 -#endif +# if (defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304) \ + || (!defined(__cpp_variable_templates) && MDSPAN_HAS_CXX_14) +# define _MDSPAN_USE_VARIABLE_TEMPLATES 1 +# endif #endif // _MDSPAN_USE_VARIABLE_TEMPLATES #ifndef _MDSPAN_USE_CONSTEXPR_14 -#if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) && MDSPAN_HAS_CXX_14 -#define _MDSPAN_USE_CONSTEXPR_14 1 -#endif +# if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) \ + || (!defined(__cpp_constexpr) && MDSPAN_HAS_CXX_14) \ + && (!(defined(__INTEL_COMPILER) && __INTEL_COMPILER <= 1700)) +# define _MDSPAN_USE_CONSTEXPR_14 1 +# endif #endif #ifndef _MDSPAN_USE_INTEGER_SEQUENCE -#ifdef _MSC_VER -#if (defined(__cpp_lib_integer_sequence) && \ - __cpp_lib_integer_sequence >= 201304) -#define _MDSPAN_USE_INTEGER_SEQUENCE 1 -#endif -#endif +# ifdef _MSC_VER +# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) +# define _MDSPAN_USE_INTEGER_SEQUENCE 1 +# endif +# endif #endif #ifndef _MDSPAN_USE_INTEGER_SEQUENCE - -#if (defined(__cpp_lib_integer_sequence) && \ - __cpp_lib_integer_sequence >= 201304) && \ - MDSPAN_HAS_CXX_14 -// several compilers lie about integer_sequence working properly unless the -// C++14 standard is used -#define _MDSPAN_USE_INTEGER_SEQUENCE 1 -#elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14 -// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to -// lie about C++14 making integer_sequence work -#define _MDSPAN_USE_INTEGER_SEQUENCE 1 -#elif defined(_MDSPAN_COMPILER_LLVMCLANG) && MDSPAN_HAS_CXX_14 -// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to -// lie about C++14 making integer_sequence work -#define _MDSPAN_USE_INTEGER_SEQUENCE 1 -#endif +# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) \ + || (!defined(__cpp_lib_integer_sequence) && MDSPAN_HAS_CXX_14) \ + /* as far as I can tell, libc++ seems to think this is a C++11 feature... */ \ + || (defined(__GLIBCXX__) && __GLIBCXX__ > 20150422 && __GNUC__ < 5 && !defined(__INTEL_CXX11_MODE__)) + // several compilers lie about integer_sequence working properly unless the C++14 standard is used +# define _MDSPAN_USE_INTEGER_SEQUENCE 1 +# elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14 + // appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to lie about C++14 making + // integer_sequence work +# define _MDSPAN_USE_INTEGER_SEQUENCE 1 +# endif #endif #ifndef _MDSPAN_USE_RETURN_TYPE_DEDUCTION -#ifdef _MSC_VER -#if !(defined(__cpp_lib_integer_sequence) && \ - __cpp_lib_integer_sequence >= 201304) && \ - MDSPAN_HAS_CXX_14 -#define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1 -#endif -#endif +# ifdef _MSC_VER +# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) && MDSPAN_HAS_CXX_14 +# define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1 +# endif +# endif #endif #ifndef _MDSPAN_USE_RETURN_TYPE_DEDUCTION -#if (defined(__cpp_return_type_deduction) && \ - __cpp_return_type_deduction >= 201304) && \ - MDSPAN_HAS_CXX_14 -#define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1 -#endif +# if (defined(__cpp_return_type_deduction) && __cpp_return_type_deduction >= 201304) \ + || (!defined(__cpp_return_type_deduction) && MDSPAN_HAS_CXX_14) +# define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1 +# endif #endif #ifndef _MDSPAN_USE_STANDARD_TRAIT_ALIASES -#if (defined(__cpp_lib_transformation_trait_aliases) && \ - __cpp_lib_transformation_trait_aliases >= 201304) -#define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1 -#elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14 -// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to -// lie about C++14 -#define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1 -#elif defined(_MDSPAN_COMPILER_LLVMCLANG) && MDSPAN_HAS_CXX_14 -// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to -// lie about C++14 -#define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1 -#endif +# if (defined(__cpp_lib_transformation_trait_aliases) && __cpp_lib_transformation_trait_aliases >= 201304) \ + || (!defined(__cpp_lib_transformation_trait_aliases) && MDSPAN_HAS_CXX_14) +# define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1 +# elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14 + // appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to lie about C++14 +# define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1 +# endif +#endif + +#ifndef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND +# if __GNUC__ < 9 +# define _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND 1 +# endif #endif #endif // _MDSPAN_INCLUDE_EXPERIMENTAL_BITS_CONFIG_HPP_ diff --git a/src/experimental/__p0009_bits/dynamic_extent.hpp b/src/experimental/__p0009_bits/dynamic_extent.hpp index 4895340dce..1d0b0ccbbb 100644 --- a/src/experimental/__p0009_bits/dynamic_extent.hpp +++ b/src/experimental/__p0009_bits/dynamic_extent.hpp @@ -43,6 +43,8 @@ #pragma once +#include "macros.hpp" + #include namespace std { diff --git a/src/experimental/__p0009_bits/extents.hpp b/src/experimental/__p0009_bits/extents.hpp index 0e0114ca08..b4dce31764 100644 --- a/src/experimental/__p0009_bits/extents.hpp +++ b/src/experimental/__p0009_bits/extents.hpp @@ -44,9 +44,12 @@ #pragma once #include "macros.hpp" -#include "mixed_size_storage.hpp" -#include "trait_backports.hpp" +#include "static_array.hpp" +#include "standard_layout_static_array.hpp" +#include "no_unique_address.hpp" +#include "trait_backports.hpp" // integer_sequence, etc. +#include #include namespace std { @@ -56,187 +59,232 @@ namespace detail { template static constexpr std::false_type _check_compatible_extents( - std::false_type, std::integer_sequence, - std::integer_sequence) noexcept { - return {}; -} + std::false_type, std::integer_sequence, std::integer_sequence +) noexcept { return { }; } template static std::integral_constant< - bool, _MDSPAN_FOLD_AND((Extents == dynamic_extent || - OtherExtents == dynamic_extent || - Extents == OtherExtents) /* && ... */ - )> + bool, + _MDSPAN_FOLD_AND( + ( + Extents == dynamic_extent + || OtherExtents == dynamic_extent + || Extents == OtherExtents + ) /* && ... */ + ) +> _check_compatible_extents( - std::true_type, std::integer_sequence, - std::integer_sequence) noexcept { - return {}; -} + std::true_type, std::integer_sequence, std::integer_sequence +) noexcept { return { }; } + +struct __extents_tag { }; } // end namespace detail -template class extents { +template +class extents + : private detail::__no_unique_address_emulation< + detail::__partially_static_sizes_tagged> +{ public: + using index_type = ptrdiff_t; -private: - using storage_type = typename detail::_make_mixed_impl< - integer_sequence>::type; + using __storage_t = detail::__partially_static_sizes_tagged; + using __base_t = detail::__no_unique_address_emulation<__storage_t>; + + private: + + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 + __storage_t& __storage() noexcept { return this->__base_t::__ref(); } + MDSPAN_FORCE_INLINE_FUNCTION + constexpr __storage_t const& __storage() const noexcept { return this->__base_t::__ref(); } template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr index_type - _static_extent_impl(size_t n, - std::integer_sequence) noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT(((Idxs == n) ? Extents : 0), - /* + ... + */ 0); + MDSPAN_FORCE_INLINE_FUNCTION + static constexpr + index_type _static_extent_impl(size_t n, std::integer_sequence) noexcept { + return _MDSPAN_FOLD_PLUS_RIGHT(((Idxs == n) ? Extents : 0), /* + ... + */ 0); } - template friend class extents; + template + friend class extents; + template - MDSPAN_INLINE_FUNCTION constexpr bool - _eq_impl(std::experimental::extents, false_type, - index_sequence) const noexcept { - return false; - } + MDSPAN_INLINE_FUNCTION + constexpr bool _eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return false; } template - MDSPAN_INLINE_FUNCTION constexpr bool - _eq_impl(std::experimental::extents other, true_type, - index_sequence) const noexcept { - return _MDSPAN_FOLD_AND((_storage.template get() == - other._storage.template get()) /* && ... */); + MDSPAN_INLINE_FUNCTION + constexpr bool _eq_impl( + std::experimental::extents other, + true_type, index_sequence + ) const noexcept { + return _MDSPAN_FOLD_AND( + (__storage().template __get_n() == other.__storage().template __get_n()) /* && ... */ + ); } template - MDSPAN_INLINE_FUNCTION constexpr bool - _not_eq_impl(std::experimental::extents, false_type, - index_sequence) const noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION + constexpr bool _not_eq_impl(std::experimental::extents, false_type, index_sequence) const noexcept { return true; } template - MDSPAN_INLINE_FUNCTION constexpr bool - _not_eq_impl(std::experimental::extents other, true_type, - index_sequence) const noexcept { - return _MDSPAN_FOLD_OR((_storage.template get() != - other._storage.template get()) /* || ... */); + MDSPAN_INLINE_FUNCTION + constexpr bool _not_eq_impl( + std::experimental::extents other, + true_type, index_sequence + ) const noexcept { + return _MDSPAN_FOLD_OR( + (this->__base_t::template __get_n() != other.template __get_n()) /* || ... */ + ); } + MDSPAN_INLINE_FUNCTION constexpr explicit + extents(__base_t&& __b) noexcept + : __base_t(::std::move(__b)) + { } + + public: + + MDSPAN_INLINE_FUNCTION static constexpr size_t rank() noexcept { return sizeof...(Extents); } MDSPAN_INLINE_FUNCTION - static constexpr size_t rank_dynamic() noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT((int(Extents == dynamic_extent)), - /* + ... + */ 0); - } + static constexpr size_t rank_dynamic() noexcept { return _MDSPAN_FOLD_PLUS_RIGHT((int(Extents == dynamic_extent)), /* + ... + */ 0); } //-------------------------------------------------------------------------------- // Constructors, Destructors, and Assignment MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents const &) noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents &&) noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents & - operator=(extents const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents & - operator=(extents &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents& operator=(extents const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents& operator=(extents&&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~extents() noexcept = default; MDSPAN_TEMPLATE_REQUIRES( - ptrdiff_t... OtherExtents, - /* requires */ ( - /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ - decltype(detail::_check_compatible_extents( - std::integral_constant{}, - std::integer_sequence{}, - std::integer_sequence{}))::value)) + ptrdiff_t... OtherExtents, + /* requires */ ( + /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ + decltype(detail::_check_compatible_extents( + std::integral_constant{}, + std::integer_sequence{}, + std::integer_sequence{} + ))::value + ) + ) MDSPAN_INLINE_FUNCTION - constexpr extents(const extents &other) noexcept - : _storage(other._storage) {} + constexpr extents(const extents& __other) + noexcept + : __base_t(__base_t{__storage_t{__other.__storage().__enable_psa_conversion()}}) + { } MDSPAN_TEMPLATE_REQUIRES( - class... Integral, - /* requires */ (_MDSPAN_FOLD_AND(std::_MDSPAN_TRAIT( - is_convertible, Integral, index_type) /* && ... */) && - sizeof...(Integral) == rank_dynamic())) + class... Integral, + /* requires */ ( + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, Integral, index_type) /* && ... */) + && sizeof...(Integral) == rank_dynamic() + ) + ) MDSPAN_INLINE_FUNCTION constexpr explicit extents(Integral... dyn) noexcept - : _storage(detail::construct_mixed_storage_from_sizes_tag, dyn...) {} + : __base_t(__base_t{typename __base_t::__stored_type{ + detail::__construct_partially_static_array_from_sizes_tag, + detail::__construct_partially_static_array_from_sizes_tag, dyn...}}) + { } + // TODO @proposal-bug this constructor should be explicit MDSPAN_TEMPLATE_REQUIRES( - class IndexType, - /* requires */ (_MDSPAN_TRAIT(is_convertible, IndexType, index_type))) + class IndexType, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, IndexType, index_type) + ) + ) MDSPAN_INLINE_FUNCTION - constexpr extents( - std::array const &dyn) noexcept - : _storage(dyn) {} + constexpr explicit + extents(std::array const& dyn) noexcept + : __base_t(__base_t{typename __base_t::stored_type{ + detail::__construct_psa_from_dynamic_values_tag_t<>{}, dyn}}) + { } MDSPAN_TEMPLATE_REQUIRES( - ptrdiff_t... OtherExtents, - /* requires */ ( - /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ - decltype(detail::_check_compatible_extents( - std::integral_constant{}, - std::integer_sequence{}, - std::integer_sequence{}))::value)) + ptrdiff_t... OtherExtents, + /* requires */ ( + /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ + decltype(detail::_check_compatible_extents( + std::integral_constant{}, + std::integer_sequence{}, + std::integer_sequence{} + ))::value + ) + ) MDSPAN_INLINE_FUNCTION - _MDSPAN_CONSTEXPR_14 extents & - operator=(const extents &other) noexcept { - _storage = other._storage; + _MDSPAN_CONSTEXPR_14 extents& operator=(const extents& other) noexcept + { + __storage() = other.__storage().__enable_psa_conversion(); return *this; } //-------------------------------------------------------------------------------- - + MDSPAN_INLINE_FUNCTION - static constexpr index_type static_extent(size_t n) noexcept { - return _static_extent_impl( - n, std::make_integer_sequence{}); + static constexpr + index_type static_extent(size_t n) noexcept { + return _static_extent_impl(n, std::make_integer_sequence{}); } MDSPAN_INLINE_FUNCTION - constexpr index_type extent(size_t n) const noexcept { - return _storage.get(n); + constexpr + index_type extent(size_t n) const noexcept { + return __storage().__get(n); } //-------------------------------------------------------------------------------- - template - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator==(extents const &lhs, extents const &rhs) noexcept { + template + MDSPAN_INLINE_FUNCTION + friend constexpr bool operator==(extents const& lhs, extents const& rhs) noexcept { return lhs._eq_impl( - rhs, - std::integral_constant{}, - make_index_sequence{}); + rhs, std::integral_constant{}, + make_index_sequence{} + ); } - template - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator!=(extents const &lhs, extents const &rhs) noexcept { + template + MDSPAN_INLINE_FUNCTION + friend constexpr bool operator!=(extents const& lhs, extents const& rhs) noexcept { return lhs._not_eq_impl( - rhs, - std::integral_constant{}, - make_index_sequence{}); + rhs, std::integral_constant{}, + make_index_sequence{} + ); + } + +public: // (but not really) + + MDSPAN_INLINE_FUNCTION static constexpr + extents __make_extents_impl(detail::__partially_static_sizes&& __bs) noexcept { + // This effectively amounts to a sideways cast that can be done in a constexpr + // context, but we have to do it to handle the case where the extents and the + // strides could accidentally end up with the same types in their hierarchies + // somehow (which would cause layout_stride::mapping to not be standard_layout) + return extents(__base_t{::std::move(__bs.template __with_tag())}); } -public: // (but not really) template - MDSPAN_FORCE_INLINE_FUNCTION constexpr index_type __extent() const noexcept { - return _storage.template get(); + MDSPAN_FORCE_INLINE_FUNCTION + constexpr + index_type __extent() const noexcept { + return __storage().template __get_n(); } - template - MDSPAN_INLINE_FUNCTION static constexpr index_type - __static_extent() noexcept { - return storage_type::template get_static(); + template + MDSPAN_INLINE_FUNCTION + static constexpr + index_type __static_extent() noexcept { + return __base_t::__stored_type::template __get_static_n(); } -private: - _MDSPAN_NO_UNIQUE_ADDRESS storage_type _storage = {}; }; } // end namespace experimental diff --git a/src/experimental/__p0009_bits/fixed_layout_impl.hpp b/src/experimental/__p0009_bits/fixed_layout_impl.hpp index 6f174b47f9..2455d74830 100644 --- a/src/experimental/__p0009_bits/fixed_layout_impl.hpp +++ b/src/experimental/__p0009_bits/fixed_layout_impl.hpp @@ -43,15 +43,15 @@ #pragma once +#include "macros.hpp" + +#include "static_array.hpp" #include "dynamic_extent.hpp" #include "extents.hpp" -#include "macros.hpp" -#include "mixed_size_storage.hpp" +#include "trait_backports.hpp" -#include #include -#include -#include +#include //============================================================================================================== @@ -62,138 +62,102 @@ namespace detail { //============================================================================================================== -template struct extents_storage { -public: - using extents_type = Extents; - -protected: - _MDSPAN_NO_UNIQUE_ADDRESS extents_type __extents = {}; - -public: - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage( - extents_storage const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage( - extents_storage &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED extents_storage & - operator=(extents_storage const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED extents_storage & - operator=(extents_storage &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED ~extents_storage() noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr extents_storage(extents_type const &exts) : __extents(exts) {} -}; - -//============================================================================================================== - template struct stride_storage_impl; template -struct stride_storage_impl, - integer_sequence, IdxConditional> - : extents_storage> { +struct stride_storage_impl, integer_sequence, IdxConditional> + : __no_unique_address_emulation> +{ protected: - using base_t = extents_storage>; - + using __base_t = __no_unique_address_emulation>; public: - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl( - stride_storage_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl( - stride_storage_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl & - operator=(stride_storage_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl & - operator=(stride_storage_impl &&) noexcept = default; + + using extents_type = experimental::extents; + + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl(stride_storage_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl(stride_storage_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl& operator=(stride_storage_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl& operator=(stride_storage_impl&&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~stride_storage_impl() noexcept = default; - using base_t::base_t; + // The layouts need to be implicitly convertible from extents (as currently specified), + // which means we need to make this not explicit here + // TODO @proposal-bug make this explicit? + MDSPAN_INLINE_FUNCTION + constexpr /* implicit */ stride_storage_impl(extents_type const& __exts) noexcept + : __base_t(__base_t{__exts}) + { } + + // The layouts need to be implicitly convertible from extents (as currently specified), + // which means we need to make this not explicit here + // TODO @proposal-bug this one isn't in the proposal? + // MDSPAN_INLINE_FUNCTION + // constexpr /* implicit */ stride_storage_impl(extents_type&& __exts) noexcept + // : __base_t{(extents_type&&)__exts} + // { } template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t get_stride() const noexcept { + MDSPAN_FORCE_INLINE_FUNCTION + constexpr ptrdiff_t get_stride() const noexcept { return _MDSPAN_FOLD_TIMES_RIGHT( - (IdxConditional{}(Idxs, N) ? base_t::__extents.template __extent() - : 1), - /* * ... * */ 1); + (IdxConditional{}(Idxs, N) ? this->__base_t::__ref().template __extent() : 1), + /* * ... * */ 1 + ); } MDSPAN_INLINE_FUNCTION constexpr ptrdiff_t get_stride(size_t n) const noexcept { return _MDSPAN_FOLD_TIMES_RIGHT( - (IdxConditional{}(Idxs, n) ? base_t::__extents.template __extent() - : 1), - /* * ... * */ 1); + (IdxConditional{}(Idxs, n) ? this->__base_t::__ref().template __extent() : 1), + /* * ... * */ 1 + ); } + }; //============================================================================================================== -template class fixed_layout_common_impl; +template +class fixed_layout_common_impl; template -class fixed_layout_common_impl, - integer_sequence, - IdxConditional> - : protected stride_storage_impl, - integer_sequence, - IdxConditional> { +class fixed_layout_common_impl, integer_sequence, IdxConditional> + : protected stride_storage_impl, integer_sequence, IdxConditional> +{ private: - using base_t = - stride_storage_impl, - integer_sequence, IdxConditional>; + + using base_t = stride_storage_impl, integer_sequence, IdxConditional>; public: - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl( - fixed_layout_common_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl( - fixed_layout_common_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl & - operator=(fixed_layout_common_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl & - operator=(fixed_layout_common_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED ~fixed_layout_common_impl() noexcept = - default; + + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl(fixed_layout_common_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl(fixed_layout_common_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl& operator=(fixed_layout_common_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl& operator=(fixed_layout_common_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED ~fixed_layout_common_impl() noexcept = default; using base_t::base_t; - MDSPAN_INLINE_FUNCTION constexpr typename base_t::extents_type extents() const - noexcept { - return this->base_t::base_t::__extents; + MDSPAN_INLINE_FUNCTION constexpr typename base_t::extents_type extents() const noexcept { + return typename base_t::extents_type(this->base_t::__ref()); }; template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t - operator()(Integral... idxs) const noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT( - (idxs * this->base_t::template get_stride()), /* + ... + */ 0); + MDSPAN_FORCE_INLINE_FUNCTION + constexpr ptrdiff_t operator()(Integral... idxs) const noexcept { + return _MDSPAN_FOLD_PLUS_RIGHT((idxs * this->base_t::template get_stride()), /* + ... + */ 0); } MDSPAN_INLINE_FUNCTION constexpr ptrdiff_t required_span_size() const noexcept { - return _MDSPAN_FOLD_TIMES_RIGHT( - (base_t::__extents.template __extent()), /* * ... * */ 1); + return _MDSPAN_FOLD_TIMES_RIGHT((base_t::__ref().template __extent()), /* * ... * */ 1); } - MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return true; } + MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { return true; } + MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr ptrdiff_t stride(size_t r) const noexcept { @@ -202,26 +166,31 @@ class fixed_layout_common_impl, //-------------------------------------------------------------------------------- -public: // (but not really) +public: // (but not really) + template - MDSPAN_INLINE_FUNCTION constexpr ptrdiff_t __stride() const noexcept { + MDSPAN_INLINE_FUNCTION + constexpr ptrdiff_t __stride() const noexcept { return this->base_t::template get_stride(); } - template struct __static_stride_workaround { + template + struct __static_stride_workaround { static constexpr ptrdiff_t __result = _MDSPAN_FOLD_TIMES_RIGHT( - (IdxConditional{}(Idxs, N) - ? base_t::extents_type::template __static_extent() - : 1), - /* * ... * */ 1); - static constexpr ptrdiff_t value = - __result == 0 ? dynamic_extent : __result; + (IdxConditional{}(Idxs, N) ? + base_t::__stored_type::template __static_extent() : 1 + ), /* * ... * */ 1 + ); + static constexpr ptrdiff_t value = __result == 0 ? dynamic_extent : __result; }; template - MDSPAN_INLINE_FUNCTION static constexpr ptrdiff_t __static_stride() noexcept { + MDSPAN_INLINE_FUNCTION + static constexpr ptrdiff_t __static_stride() noexcept + { return __static_stride_workaround::value; } + }; //============================================================================================================== diff --git a/src/experimental/__p0009_bits/layout_left.hpp b/src/experimental/__p0009_bits/layout_left.hpp index 05ac33720c..c3bf7cc3a1 100644 --- a/src/experimental/__p0009_bits/layout_left.hpp +++ b/src/experimental/__p0009_bits/layout_left.hpp @@ -43,8 +43,8 @@ #pragma once -#include "fixed_layout_impl.hpp" #include "macros.hpp" +#include "fixed_layout_impl.hpp" #include "trait_backports.hpp" namespace std { @@ -67,88 +67,84 @@ template class layout_left_impl; template class layout_left_impl> - : public fixed_layout_common_impl, - make_index_sequence, - layout_left_idx_conditional> { + : public fixed_layout_common_impl, make_index_sequence, layout_left_idx_conditional> +{ private: - using idx_seq = make_index_sequence; - using base_t = fixed_layout_common_impl, - make_index_sequence, - layout_left_idx_conditional>; - template friend class layout_left_impl; +using idx_seq = make_index_sequence; + using base_t = fixed_layout_common_impl, make_index_sequence, layout_left_idx_conditional>; + + template + friend class layout_left_impl; public: + //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl( - layout_left_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl( - layout_left_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl & - operator=(layout_left_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl & - operator=(layout_left_impl &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl(layout_left_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl(layout_left_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl& operator=(layout_left_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl& operator=(layout_left_impl&&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_left_impl() noexcept = default; using base_t::base_t; // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class OtherExtents, - /* requires */ (_MDSPAN_TRAIT(is_convertible, OtherExtents, - std::experimental::extents))) + class OtherExtents, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents) + ) + ) MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - layout_left_impl(layout_left_impl const - &other) // NOLINT(google-explicit-constructor) - : base_t(other.extents()) {} + layout_left_impl(layout_left_impl const& other) // NOLINT(google-explicit-constructor) + : base_t(other.extents()) + { } + // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class OtherExtents, - /* requires */ (_MDSPAN_TRAIT(is_convertible, OtherExtents, - std::experimental::extents))) - MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 layout_left_impl & - operator=(layout_left_impl const &other) { - this->__extents = other.extents(); + class OtherExtents, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents) + ) + ) + MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 + layout_left_impl& operator=(layout_left_impl const& other) + { + this->base_t::__ref() = other.extents(); return *this; } //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return true; } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } // TODO @proposal-bug these (and other analogous operators) should be non-member functions - template - MDSPAN_INLINE_FUNCTION constexpr bool - operator==(layout_left_impl const &other) const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator==(layout_left_impl const& other) const noexcept { return this->base_t::extents() == other.extents(); } - template - MDSPAN_INLINE_FUNCTION constexpr bool - operator!=(layout_left_impl const &other) const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator!=(layout_left_impl const& other) const noexcept { return this->base_t::extents() != other.extents(); } + }; -} // namespace detail +} // namespace detail //============================================================================== struct layout_left { - template using mapping = detail::layout_left_impl; + template + using mapping = detail::layout_left_impl; }; + } // end namespace experimental } // end namespace std \ No newline at end of file diff --git a/src/experimental/__p0009_bits/layout_right.hpp b/src/experimental/__p0009_bits/layout_right.hpp index 3e66957ee5..3ccf45c1de 100644 --- a/src/experimental/__p0009_bits/layout_right.hpp +++ b/src/experimental/__p0009_bits/layout_right.hpp @@ -43,8 +43,8 @@ #pragma once -#include "fixed_layout_impl.hpp" #include "macros.hpp" +#include "fixed_layout_impl.hpp" #include "trait_backports.hpp" namespace std { @@ -54,11 +54,12 @@ namespace experimental { namespace detail { + struct layout_right_idx_conditional { MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_idx_conditional() noexcept = default; MDSPAN_FORCE_INLINE_FUNCTION - constexpr /*inline*/ bool operator()(size_t Idx, size_t N) const noexcept { + constexpr bool operator()(size_t Idx, size_t N) const noexcept { return Idx > N; }; }; @@ -67,80 +68,73 @@ template class layout_right_impl; template class layout_right_impl> - : public fixed_layout_common_impl, - make_index_sequence, - layout_right_idx_conditional> { + : public fixed_layout_common_impl, make_index_sequence, layout_right_idx_conditional> +{ private: + using idx_seq = make_index_sequence; - using base_t = fixed_layout_common_impl, - make_index_sequence, - layout_right_idx_conditional>; + using base_t = fixed_layout_common_impl, make_index_sequence, layout_right_idx_conditional>; - template friend class layout_right_impl; + template + friend class layout_right_impl; public: + //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl( - layout_right_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl( - layout_right_impl &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl & - operator=(layout_right_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl & - operator=(layout_right_impl &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl(layout_right_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl(layout_right_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl& operator=(layout_right_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl& operator=(layout_right_impl&&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_right_impl() noexcept = default; using base_t::base_t; // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class OtherExtents, - /* requires */ (_MDSPAN_TRAIT(is_convertible, OtherExtents, - std::experimental::extents))) + class OtherExtents, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents) + ) + ) MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - layout_right_impl(layout_right_impl const - &other) // NOLINT(google-explicit-constructor) - : base_t(other.extents()) {} + layout_right_impl(layout_right_impl const& other) // NOLINT(google-explicit-constructor) + : base_t(other.extents()) + { } // TODO noexcept specification MDSPAN_TEMPLATE_REQUIRES( - class OtherExtents, - /* requires */ (_MDSPAN_TRAIT(is_convertible, OtherExtents, - std::experimental::extents))) - MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 layout_right_impl & - operator=(layout_right_impl const &other) { - this->__extents = other.extents(); + class OtherExtents, + /* requires */ ( + _MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents) + ) + ) + MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 + layout_right_impl& operator=(layout_right_impl const& other) + { + this->base_t::__ref() = other.extents(); return *this; } //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { - return true; - } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return true; } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } // TODO @proposal-bug these (and other analogous operators) should be non-member functions - template - MDSPAN_INLINE_FUNCTION constexpr bool - operator==(layout_right_impl const &other) const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator==(layout_right_impl const& other) const noexcept { return this->base_t::extents() == other.extents(); } - template - MDSPAN_INLINE_FUNCTION constexpr bool - operator!=(layout_right_impl const &other) const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator!=(layout_right_impl const& other) const noexcept { return this->base_t::extents() != other.extents(); } + }; } // namespace detail @@ -148,8 +142,10 @@ class layout_right_impl> //============================================================================== struct layout_right { - template using mapping = detail::layout_right_impl; + template + using mapping = detail::layout_right_impl; }; + } // end namespace experimental } // end namespace std \ No newline at end of file diff --git a/src/experimental/__p0009_bits/layout_stride.hpp b/src/experimental/__p0009_bits/layout_stride.hpp index ffcf909e20..54981b24b4 100644 --- a/src/experimental/__p0009_bits/layout_stride.hpp +++ b/src/experimental/__p0009_bits/layout_stride.hpp @@ -43,14 +43,15 @@ #pragma once -#include "extents.hpp" -#include "fixed_layout_impl.hpp" #include "macros.hpp" -#include "mixed_size_storage.hpp" +#include "fixed_layout_impl.hpp" +#include "static_array.hpp" +#include "extents.hpp" +#include "trait_backports.hpp" #include -#include #include +#include namespace std { namespace experimental { @@ -62,168 +63,218 @@ namespace detail { template class layout_stride_impl; template -class layout_stride_impl, Strides...> - : public extents_storage> { +class layout_stride_impl< + std::experimental::extents, Strides... +> : private __no_unique_address_emulation< + __compressed_pair< + ::std::experimental::extents, + __partially_static_sizes + > + > +{ +public: + using extents_type = experimental::extents; private: - using base_t = extents_storage>; + using idx_seq = make_index_sequence; - using stride_storage_t = - typename _make_mixed_impl>::type; + //---------------------------------------------------------------------------- + + using __strides_storage_t = __partially_static_sizes; + using __member_pair_t = __compressed_pair; + using __base_t = __no_unique_address_emulation<__member_pair_t>; + + MDSPAN_FORCE_INLINE_FUNCTION constexpr __strides_storage_t const& + __strides_storage() const noexcept { return this->__base_t::__ref().__second(); } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __strides_storage_t& + __strides_storage() noexcept { return this->__base_t::__ref().__second(); } - template friend class layout_stride_impl; + //---------------------------------------------------------------------------- + + template + friend class layout_stride_impl; + + //---------------------------------------------------------------------------- // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level - template > struct __impl; + template > + struct __impl; - template struct __impl> { + template + struct __impl> + { template - MDSPAN_INLINE_FUNCTION static constexpr bool - _eq_impl(layout_stride_impl const &self, - layout_stride_impl const - &other) noexcept { - return _MDSPAN_FOLD_AND((self.template __stride() == - other.template __stride()) /* && ... */); + MDSPAN_INLINE_FUNCTION + static constexpr bool _eq_impl(layout_stride_impl const& self, layout_stride_impl const& other) noexcept { + return _MDSPAN_FOLD_AND((self.template __stride() == other.template __stride()) /* && ... */); } template - MDSPAN_INLINE_FUNCTION static constexpr bool - _not_eq_impl(layout_stride_impl const &self, - layout_stride_impl const - &other) noexcept { - return _MDSPAN_FOLD_OR((self.template __stride() != - other.template __stride()) /* || ... */); + MDSPAN_INLINE_FUNCTION + static constexpr bool _not_eq_impl(layout_stride_impl const& self, layout_stride_impl const& other) noexcept { + return _MDSPAN_FOLD_OR((self.template __stride() != other.template __stride()) /* || ... */); } template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ptrdiff_t - _call_op_impl(layout_stride_impl const &self, Integral... idxs) noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT((idxs * self.template __stride()), - /* + ... + */ 0); + MDSPAN_FORCE_INLINE_FUNCTION + static constexpr ptrdiff_t _call_op_impl(layout_stride_impl const& self, Integral... idxs) noexcept { + return _MDSPAN_FOLD_PLUS_RIGHT((idxs * self.template __stride()), /* + ... + */ 0); } MDSPAN_INLINE_FUNCTION - static constexpr size_t - _req_span_size_impl(layout_stride_impl const &self) noexcept { + static constexpr size_t _req_span_size_impl(layout_stride_impl const& self) noexcept { // assumes no negative strides; not sure if I'm allowed to assume that or not - return __impl::_call_op_impl( - self, (self.extents().template __extent() - 1)...) + - 1; + return __impl::_call_op_impl(self, (self.extents().template __extent() - 1)...) + 1; } }; + //---------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION constexpr explicit + layout_stride_impl( + __base_t&& __b + ) : __base_t(::std::move(__b)) {} + + //---------------------------------------------------------------------------- + public: // (but not really) + template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t __stride() const noexcept { - return _strides.template get(); + MDSPAN_FORCE_INLINE_FUNCTION + constexpr ptrdiff_t __stride() const noexcept { + return __strides_storage().template __get_n(); } - template struct __static_stride_workaround { - static constexpr ptrdiff_t value = - stride_storage_t::template get_static(); + template + struct __static_stride_workaround { + static constexpr ptrdiff_t value = __strides_storage_t::template __get_static_n(); }; template - MDSPAN_INLINE_FUNCTION static constexpr ptrdiff_t __static_stride() noexcept { - return stride_storage_t::template get_static(); + MDSPAN_INLINE_FUNCTION + static constexpr ptrdiff_t __static_stride() noexcept + { + return __strides_storage_t::template __get_static_n(); + } + + MDSPAN_INLINE_FUNCTION + static constexpr layout_stride_impl + __make_layout_stride_impl( + __partially_static_sizes&& __exts, + __partially_static_sizes&& __strs + ) noexcept { + // call the private constructor we created for this purpose + return layout_stride_impl( + __base_t{ + __member_pair_t( + extents_type::__make_extents_impl(::std::move(__exts)), + ::std::move(__strs) + ) + } + ); } public: + //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl( - layout_stride_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl( - layout_stride_impl &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl(layout_stride_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl(layout_stride_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED + layout_stride_impl& operator=(layout_stride_impl const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED + layout_stride_impl& operator=(layout_stride_impl&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_stride_impl() noexcept = default; // TODO @proposal-bug layout stride needs this constructor MDSPAN_INLINE_FUNCTION - constexpr layout_stride_impl( - std::experimental::extents const &e, - array const &strides) noexcept - : base_t(e), _strides(strides) {} - - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_stride_impl & - operator=(layout_stride_impl const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED layout_stride_impl & - operator=(layout_stride_impl &&) noexcept = default; - - MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_stride_impl() noexcept = default; - - using base_t::base_t; - - // TODO conversion constructors and assignment + constexpr + layout_stride_impl( + std::experimental::extents const& e, + array const& strides + ) noexcept + : __base_t(__base_t{__member_pair_t(e, __strides_storage_t(__construct_psa_from_dynamic_values_tag_t<>{}, strides))}) + { } + + // TODO @proposal-bug @proposal-extension layout stride needs this constructor + // clang-format off + MDSPAN_FUNCTION_REQUIRES( + (MDSPAN_INLINE_FUNCTION constexpr explicit), + layout_stride_impl, (std::experimental::extents const& e), noexcept, + /* requires */ ( + // remember that this also covers the zero strides case because an && fold on an empty pack is true +#if defined(__INTEL_COMPILER) + // Work-around for an ICE. layout_stride won't properly SFINAE with ICC, but oh well + true +#else + _MDSPAN_FOLD_AND(Strides != dynamic_extent /* && ... */) +#endif + ) + ) : __base_t(__base_t{__member_pair_t(e, __strides_storage_t())}) + { } + // clang-format on + +// TODO conversion constructors and assignment //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION constexpr typename base_t::extents_type extents() const - noexcept { - return this->base_t::__extents; + MDSPAN_INLINE_FUNCTION constexpr extents_type extents() const noexcept { + return this->__base_t::__ref().__first(); }; - MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return true; } // TODO @proposal-bug this wording for this is (at least slightly) broken (should at least be "... stride(p[0]) == 1...") - MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 bool is_contiguous() const - noexcept { + MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 bool is_contiguous() const noexcept { // TODO @testing test layout_stride is_contiguous() - auto rem = std::array{}; + auto rem = array{ }; std::iota(rem.begin(), rem.end(), ptrdiff_t(0)); auto next_idx_iter = std::find_if( - rem.begin(), rem.end(), [&](ptrdiff_t i) { _strides.get(i) == 1; }); - if (next_idx_iter != rem.end()) { + rem.begin(), rem.end(), + [&](ptrdiff_t i) { this->stride(i) == 1; } + ); + if(next_idx_iter != rem.end()) { ptrdiff_t prev_stride_times_prev_extent = - this->extents().extent(*next_idx_iter) * _strides.get(*next_idx_iter); + this->extents().extent(*next_idx_iter) * this->stride(*next_idx_iter); // "remove" the index constexpr ptrdiff_t removed_index_sentinel = -1; *next_idx_iter = removed_index_sentinel; int found_count = 1; while (found_count != sizeof...(Exts)) { - next_idx_iter = std::find_if(rem.begin(), rem.end(), [&](ptrdiff_t i) { - return i != removed_index_sentinel && - _strides.get(i) * this->extents().extent(i) == - prev_stride_times_prev_extent; - }); + next_idx_iter = std::find_if( + rem.begin(), rem.end(), + [&](ptrdiff_t i) { + return i != removed_index_sentinel + && this->stride(i) * this->extents().extent(i) == prev_stride_times_prev_extent; + } + ); if (next_idx_iter != rem.end()) { // "remove" the index *next_idx_iter = removed_index_sentinel; ++found_count; - prev_stride_times_prev_extent = - _strides.get(*next_idx_iter) * - this->extents().extent(*next_idx_iter); - } else { - break; - } + prev_stride_times_prev_extent = stride(*next_idx_iter) * this->extents().extent(*next_idx_iter); + } else { break; } } return found_count == sizeof...(Exts); } return false; } - MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { // TODO @proposal-bug this will need to be updated with the incorporation of static strides into the layout stride definition // TODO this should actually check whether we know statically from the strides if this is always contiguous return false; } - MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { - return true; - } + MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_TEMPLATE_REQUIRES( - class... Indices, - /* requires */ (sizeof...(Indices) == sizeof...(Exts) && - _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_constructible, Indices, - ptrdiff_t) /*&& ...*/))) + class... Indices, + /* requires */ ( + sizeof...(Indices) == sizeof...(Exts) && + _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_constructible, Indices, ptrdiff_t) /*&& ...*/) + ) + ) MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t operator()(Indices... idxs) const noexcept { return __impl<>::_call_op_impl(*this, idxs...); @@ -231,7 +282,7 @@ class layout_stride_impl, Strides...> MDSPAN_INLINE_FUNCTION constexpr ptrdiff_t stride(size_t r) const noexcept { - return _strides.get(r); + return __strides_storage().__get(r); } MDSPAN_INLINE_FUNCTION @@ -243,32 +294,32 @@ class layout_stride_impl, Strides...> // TODO @proposal-bug these (and other analogous operators) should be non-member functions // TODO @proposal-bug these should do more than just compare extents! - template - MDSPAN_INLINE_FUNCTION constexpr bool operator==( - layout_stride_impl const &other) - const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator==(layout_stride_impl const& other) const noexcept { return __impl<>::_eq_impl(*this, other); } - template - MDSPAN_INLINE_FUNCTION constexpr bool operator!=( - layout_stride_impl const &other) - const noexcept { + template + MDSPAN_INLINE_FUNCTION + constexpr bool operator!=(layout_stride_impl const& other) const noexcept { return __impl<>::_not_eq_impl(*this, other); } -private: - _MDSPAN_NO_UNIQUE_ADDRESS stride_storage_t _strides = {}; }; } // namespace detail //============================================================================== + // TODO @proposal-bug layout_stride needs these non-type template parameters -template struct layout_stride { +template +struct layout_stride { template - using mapping = detail::layout_stride_impl; + using mapping = detail::layout_stride_impl< + Extents, StaticStrides... + >; }; } // end namespace experimental diff --git a/src/experimental/__p0009_bits/macros.hpp b/src/experimental/__p0009_bits/macros.hpp index 0f6c21eacf..bef124f89f 100644 --- a/src/experimental/__p0009_bits/macros.hpp +++ b/src/experimental/__p0009_bits/macros.hpp @@ -41,6 +41,7 @@ //@HEADER */ + #pragma once #include "config.hpp" @@ -48,75 +49,87 @@ #include // std::is_void #ifndef MDSPAN_FORCE_INLINE_FUNCTION -#ifdef _MSC_VER // Microsoft compilers -#define MDSPAN_FORCE_INLINE_FUNCTION __forceinline -#elif defined(__CUDA_ARCH__) -#define MDSPAN_FORCE_INLINE_FUNCTION \ - __attribute__((always_inline)) __host__ __device__ -#else -#define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) -#endif +# ifdef _MSC_VER // Microsoft compilers +# define MDSPAN_FORCE_INLINE_FUNCTION __forceinline +# elif defined(__CUDA_ARCH__) +# define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) __host__ __device__ +# else +# define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) +# endif #endif #ifndef MDSPAN_INLINE_FUNCTION -#if defined(__CUDA_ARCH__) -#define MDSPAN_INLINE_FUNCTION inline __host__ __device__ -#else -#define MDSPAN_INLINE_FUNCTION inline -#endif +# if defined(__CUDA_ARCH__) +# define MDSPAN_INLINE_FUNCTION inline __host__ __device__ +# else +# define MDSPAN_INLINE_FUNCTION inline +# endif #endif #ifndef MDSPAN_INLINE_FUNCTION_DEFAULTED -#define MDSPAN_INLINE_FUNCTION_DEFAULTED inline +# define MDSPAN_INLINE_FUNCTION_DEFAULTED inline #endif //============================================================================== // {{{1 + #ifdef _MSC_VER // Microsoft compilers -#define MDSPAN_PP_COUNT(...) \ - _MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE( \ - _MDSPAN_PP_INTERNAL_ARGS_AUGMENTER(__VA_ARGS__)) +#define MDSPAN_PP_COUNT(...) \ + _MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE( \ + _MDSPAN_PP_INTERNAL_ARGS_AUGMENTER(__VA_ARGS__) \ + ) #define _MDSPAN_PP_INTERNAL_ARGS_AUGMENTER(...) unused, __VA_ARGS__ #define _MDSPAN_PP_INTERNAL_EXPAND(x) x -#define _MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE(...) \ - _MDSPAN_PP_INTERNAL_EXPAND(_MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ - __VA_ARGS__, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, \ - 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, \ - 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \ - 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) -#define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ - _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10, _11, _12, _13, _14, _15, \ - _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ - _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, \ - _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ - _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, count, ...) \ - count /**/ +#define _MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE(...) \ + _MDSPAN_PP_INTERNAL_EXPAND( \ + _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ + __VA_ARGS__, 69, 68, 67, 66, 65, 64, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \ + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, \ + 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, \ + 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, \ + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 \ + ) \ + ) +# define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ + _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, \ + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \ + _70, count, ...) count \ + /**/ #else // Non-Microsoft compilers -#define MDSPAN_PP_COUNT(...) \ - _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ - 0, ##__VA_ARGS__, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, \ - 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ - 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, \ - 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, \ - 1, 0) \ - /**/ -#define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ - _0_, _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10, _11, _12, _13, _14, \ - _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ - _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, \ - _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ - _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, count, ...) \ - count /**/ +# define MDSPAN_PP_COUNT(...) \ + _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ + 0, ## __VA_ARGS__, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \ + 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, \ + 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \ + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) \ + /**/ +# define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \ + _0_, _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, \ + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \ + _70, count, ...) count \ + /**/ #endif #define MDSPAN_PP_STRINGIFY_IMPL(x) #x #define MDSPAN_PP_STRINGIFY(x) MDSPAN_PP_STRINGIFY_IMPL(x) -#define MDSPAN_PP_CAT_IMPL(x, y) x##y +#define MDSPAN_PP_CAT_IMPL(x, y) x ## y #define MDSPAN_PP_CAT(x, y) MDSPAN_PP_CAT_IMPL(x, y) #define MDSPAN_PP_EVAL(X, ...) X(__VA_ARGS__) @@ -133,50 +146,63 @@ // These compatibility macros don't help with partial ordering, but they should do the trick // for what we need to do with concepts in mdspan #ifdef _MDSPAN_USE_CONCEPTS -#define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) > requires REQ -#define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, \ - REQ) \ - MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) \ - FNAME PAREN_PARAMS QUALS requires REQ /**/ +# define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) > requires REQ +# define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, REQ) \ + MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) FNAME PAREN_PARAMS QUALS requires REQ \ + /**/ #else -#define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \ - , int = std::enable_if_t<(REQ), int>(0) > -#define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, \ - REQ) \ - MDSPAN_TEMPLATE_REQUIRES( \ - class __function_requires_ignored = void, \ - (std::is_void<__function_requires_ignored>::value && REQ)) \ - MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) FNAME PAREN_PARAMS QUALS /**/ +# define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) , typename ::std::enable_if<(REQ), int>::type = 0> +# define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, REQ) \ + MDSPAN_TEMPLATE_REQUIRES( \ + class __function_requires_ignored=void, \ + (std::is_void<__function_requires_ignored>::value && REQ) \ + ) MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) FNAME PAREN_PARAMS QUALS \ + /**/ #endif + #ifdef _MSC_VER -#define MDSPAN_TEMPLATE_REQUIRES(...) \ - MDSPAN_PP_CAT(MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, \ - MDSPAN_PP_COUNT(__VA_ARGS__))(__VA_ARGS__), ) \ - /**/ +# define MDSPAN_TEMPLATE_REQUIRES(...) \ + MDSPAN_PP_CAT( \ + MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, MDSPAN_PP_COUNT(__VA_ARGS__))\ + (__VA_ARGS__), \ + ) \ + /**/ #else -#define MDSPAN_TEMPLATE_REQUIRES(...) \ - MDSPAN_PP_EVAL( \ - MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, MDSPAN_PP_COUNT(__VA_ARGS__)), \ - __VA_ARGS__) \ - /**/ +# define MDSPAN_TEMPLATE_REQUIRES(...) \ + MDSPAN_PP_EVAL( \ + MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, MDSPAN_PP_COUNT(__VA_ARGS__)), \ + __VA_ARGS__ \ + ) \ + /**/ #endif -#define MDSPAN_TEMPLATE_REQUIRES_2(TP1, REQ) \ - template end Concept emulation }}}1 @@ -185,10 +211,10 @@ //============================================================================== // {{{1 -#ifdef _MDSPAN_USE_INLINE_VARIABLES -#define _MDSPAN_INLINE_VARIABLE inline +#if _MDSPAN_USE_INLINE_VARIABLES +# define _MDSPAN_INLINE_VARIABLE inline #else -#define _MDSPAN_INLINE_VARIABLE +# define _MDSPAN_INLINE_VARIABLE #endif // end inline variables }}}1 @@ -198,24 +224,19 @@ // {{{1 #if _MDSPAN_USE_RETURN_TYPE_DEDUCTION -#define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ - auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { \ - return MDSPAN_PP_REMOVE_PARENS(BODY); \ - } -#define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ - decltype(auto) MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { \ - return MDSPAN_PP_REMOVE_PARENS(BODY); \ - } +# define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ + auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { return MDSPAN_PP_REMOVE_PARENS(BODY); } +# define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ + decltype(auto) MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { return MDSPAN_PP_REMOVE_PARENS(BODY); } #else -#define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ - auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE)->typename std:: \ - remove_cv::type>::type { \ - return MDSPAN_PP_REMOVE_PARENS(BODY); \ - } -#define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ - auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE)->decltype(BODY) { \ - return MDSPAN_PP_REMOVE_PARENS(BODY); \ - } +# define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ + auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) \ + -> typename std::remove_cv::type>::type \ + { return MDSPAN_PP_REMOVE_PARENS(BODY); } +# define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \ + auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) \ + -> decltype(BODY) \ + { return MDSPAN_PP_REMOVE_PARENS(BODY); } #endif @@ -225,17 +246,17 @@ //============================================================================== // {{{1 -struct __mdspan_enable_fold_comma {}; +struct __mdspan_enable_fold_comma { }; #ifdef _MDSPAN_USE_FOLD_EXPRESSIONS -#define _MDSPAN_FOLD_AND(...) ((__VA_ARGS__) && ...) -#define _MDSPAN_FOLD_AND_TEMPLATE(...) ((__VA_ARGS__) && ...) -#define _MDSPAN_FOLD_OR(...) ((__VA_ARGS__) || ...) -#define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) (INIT = ... = (__VA_ARGS__)) -#define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) (PACK = ... = (__VA_ARGS__)) -#define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) (PACK * ... * (__VA_ARGS__)) -#define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) (PACK + ... + (__VA_ARGS__)) -#define _MDSPAN_FOLD_COMMA(...) ((__VA_ARGS__), ...) +# define _MDSPAN_FOLD_AND(...) ((__VA_ARGS__) && ...) +# define _MDSPAN_FOLD_AND_TEMPLATE(...) ((__VA_ARGS__) && ...) +# define _MDSPAN_FOLD_OR(...) ((__VA_ARGS__) || ...) +# define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) (INIT = ... = (__VA_ARGS__)) +# define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) (PACK = ... = (__VA_ARGS__)) +# define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) (PACK * ... * (__VA_ARGS__)) +# define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) (PACK + ... + (__VA_ARGS__)) +# define _MDSPAN_FOLD_COMMA(...) ((__VA_ARGS__), ...) #else namespace std { @@ -248,75 +269,73 @@ namespace __fold_compatibility_impl { #if _MDSPAN_USE_RETURN_TYPE_DEDUCTION MDSPAN_FORCE_INLINE_FUNCTION -constexpr decltype(auto) __fold_right_and_impl() { return true; } +constexpr decltype(auto) __fold_right_and_impl() { + return true; +} template -MDSPAN_FORCE_INLINE_FUNCTION constexpr decltype(auto) -__fold_right_and_impl(Arg &&arg, Args &&... args) { - return ((Arg &&) arg) && - __fold_compatibility_impl::__fold_right_and_impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr decltype(auto) __fold_right_and_impl(Arg&& arg, Args&&... args) { + return ((Arg&&)arg) && __fold_compatibility_impl::__fold_right_and_impl((Args&&)args...); } MDSPAN_FORCE_INLINE_FUNCTION -constexpr decltype(auto) __fold_right_or_impl() { return false; } +constexpr decltype(auto) __fold_right_or_impl() { + return false; +} template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_or_impl(Arg &&arg, Args &&... args) { - return ((Arg &&) arg) || - __fold_compatibility_impl::__fold_right_or_impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_or_impl(Arg&& arg, Args&&... args) { + return ((Arg&&)arg) || __fold_compatibility_impl::__fold_right_or_impl((Args&&)args...); } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_left_assign_impl(Arg1 &&arg1) { - return (Arg1 &&) arg1; +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_left_assign_impl(Arg1&& arg1) { + return (Arg1&&)arg1; } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_left_assign_impl(Arg1 &&arg1, Arg2 &&arg2, Args &&... args) { - return __fold_compatibility_impl::__fold_left_assign_impl( - (((Arg1 &&) arg1) = ((Arg2 &&) arg2)), (Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_left_assign_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) { + return __fold_compatibility_impl::__fold_left_assign_impl((((Arg1&&)arg1) = ((Arg2&&)arg2)), (Args&&)args...); } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_assign_impl(Arg1 &&arg1) { - return (Arg1 &&) arg1; +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_assign_impl(Arg1&& arg1) { + return (Arg1&&)arg1; } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_assign_impl(Arg1 &&arg1, Arg2 &&arg2, Args &&... args) { - return ((Arg1 &&) arg1) = __fold_compatibility_impl::__fold_right_assign_impl( - (Arg2 &&) arg2, (Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_assign_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) { + return ((Arg1&&)arg1) = __fold_compatibility_impl::__fold_right_assign_impl((Arg2&&)arg2, (Args&&)args...); } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_plus_impl(Arg1 &&arg1) { - return (Arg1 &&) arg1; +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_plus_impl(Arg1&& arg1) { + return (Arg1&&)arg1; } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_plus_impl(Arg1 &&arg1, Arg2 &&arg2, Args &&... args) { - return ((Arg1 &&) arg1) + __fold_compatibility_impl::__fold_right_plus_impl( - (Arg2 &&) arg2, (Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_plus_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) { + return ((Arg1&&)arg1) + __fold_compatibility_impl::__fold_right_plus_impl((Arg2&&)arg2, (Args&&)args...); } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_times_impl(Arg1 &&arg1) { - return (Arg1 &&) arg1; +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_times_impl(Arg1&& arg1) { + return (Arg1&&)arg1; } template -MDSPAN_FORCE_INLINE_FUNCTION constexpr auto -__fold_right_times_impl(Arg1 &&arg1, Arg2 &&arg2, Args &&... args) { - return ((Arg1 &&) arg1) * __fold_compatibility_impl::__fold_right_times_impl( - (Arg2 &&) arg2, (Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr auto __fold_right_times_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) { + return ((Arg1&&)arg1) * __fold_compatibility_impl::__fold_right_times_impl((Arg2&&)arg2, (Args&&)args...); } #else @@ -324,28 +343,33 @@ __fold_right_times_impl(Arg1 &&arg1, Arg2 &&arg2, Args &&... args) { //------------------------------------------------------------------------------ // {{{2 -template struct __fold_right_and_impl_; -template <> struct __fold_right_and_impl_<> { +template +struct __fold_right_and_impl_; +template <> +struct __fold_right_and_impl_<> { using __rv = bool; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl() noexcept { return true; } + static constexpr __rv + __impl() noexcept { + return true; + } }; template struct __fold_right_and_impl_ { using __next_t = __fold_right_and_impl_; - using __rv = - decltype(std::declval() && std::declval()); + using __rv = decltype(std::declval() && std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg, Args &&... args) noexcept { - return ((Arg &&) arg) && __next_t::__impl((Args &&) args...); + static constexpr __rv + __impl(Arg&& arg, Args&&... args) noexcept { + return ((Arg&&)arg) && __next_t::__impl((Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_right_and_impl_::__rv - __fold_right_and_impl(Args &&... args) { - return __fold_right_and_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_right_and_impl_::__rv +__fold_right_and_impl(Args&&... args) { + return __fold_right_and_impl_::__impl((Args&&)args...); } // end right and }}}2 @@ -354,27 +378,33 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr //------------------------------------------------------------------------------ // {{{2 -template struct __fold_right_or_impl_; -template <> struct __fold_right_or_impl_<> { +template +struct __fold_right_or_impl_; +template <> +struct __fold_right_or_impl_<> { using __rv = bool; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl() noexcept { return false; } + static constexpr __rv + __impl() noexcept { + return false; + } }; -template struct __fold_right_or_impl_ { +template +struct __fold_right_or_impl_ { using __next_t = __fold_right_or_impl_; - using __rv = - decltype(std::declval() || std::declval()); + using __rv = decltype(std::declval() || std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg, Args &&... args) noexcept { - return ((Arg &&) arg) || __next_t::__impl((Args &&) args...); + static constexpr __rv + __impl(Arg&& arg, Args&&... args) noexcept { + return ((Arg&&)arg) || __next_t::__impl((Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_right_or_impl_::__rv - __fold_right_or_impl(Args &&... args) { - return __fold_right_or_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_right_or_impl_::__rv +__fold_right_or_impl(Args&&... args) { + return __fold_right_or_impl_::__impl((Args&&)args...); } // end right or }}}2 @@ -383,30 +413,33 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr //------------------------------------------------------------------------------ // {{{2 -template struct __fold_right_plus_impl_; -template struct __fold_right_plus_impl_ { - using __rv = Arg &&; +template +struct __fold_right_plus_impl_; +template +struct __fold_right_plus_impl_ { + using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg) noexcept { return (Arg &&) arg; } + static constexpr __rv + __impl(Arg&& arg) noexcept { + return (Arg&&)arg; + } }; template struct __fold_right_plus_impl_ { using __next_t = __fold_right_plus_impl_; - using __rv = - decltype(std::declval() + std::declval()); + using __rv = decltype(std::declval() + std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg1 &&arg, Arg2 &&arg2, - Args &&... args) noexcept { - return ((Arg1 &&) arg) + - __next_t::__impl((Arg2 &&) arg2, (Args &&) args...); + static constexpr __rv + __impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + return ((Arg1&&)arg) + __next_t::__impl((Arg2&&)arg2, (Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_right_plus_impl_::__rv - __fold_right_plus_impl(Args &&... args) { - return __fold_right_plus_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_right_plus_impl_::__rv +__fold_right_plus_impl(Args&&... args) { + return __fold_right_plus_impl_::__impl((Args&&)args...); } // end right plus }}}2 @@ -415,30 +448,33 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr //------------------------------------------------------------------------------ // {{{2 -template struct __fold_right_times_impl_; -template struct __fold_right_times_impl_ { - using __rv = Arg &&; +template +struct __fold_right_times_impl_; +template +struct __fold_right_times_impl_ { + using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg) noexcept { return (Arg &&) arg; } + static constexpr __rv + __impl(Arg&& arg) noexcept { + return (Arg&&)arg; + } }; template struct __fold_right_times_impl_ { using __next_t = __fold_right_times_impl_; - using __rv = - decltype(std::declval() * std::declval()); + using __rv = decltype(std::declval() * std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg1 &&arg, Arg2 &&arg2, - Args &&... args) noexcept { - return ((Arg1 &&) arg) * - __next_t::__impl((Arg2 &&) arg2, (Args &&) args...); + static constexpr __rv + __impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + return ((Arg1&&)arg) * __next_t::__impl((Arg2&&)arg2, (Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_right_times_impl_::__rv - __fold_right_times_impl(Args &&... args) { - return __fold_right_times_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_right_times_impl_::__rv +__fold_right_times_impl(Args&&... args) { + return __fold_right_times_impl_::__impl((Args&&)args...); } // end right times }}}2 @@ -447,30 +483,33 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr //------------------------------------------------------------------------------ // {{{2 -template struct __fold_right_assign_impl_; -template struct __fold_right_assign_impl_ { - using __rv = Arg &&; +template +struct __fold_right_assign_impl_; +template +struct __fold_right_assign_impl_ { + using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg) noexcept { return (Arg &&) arg; } + static constexpr __rv + __impl(Arg&& arg) noexcept { + return (Arg&&)arg; + } }; template struct __fold_right_assign_impl_ { using __next_t = __fold_right_assign_impl_; - using __rv = - decltype(std::declval() = std::declval()); + using __rv = decltype(std::declval() = std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg1 &&arg, Arg2 &&arg2, - Args &&... args) noexcept { - return ((Arg1 &&) arg) = - __next_t::__impl((Arg2 &&) arg2, (Args &&) args...); + static constexpr __rv + __impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + return ((Arg1&&)arg) = __next_t::__impl((Arg2&&)arg2, (Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_right_assign_impl_::__rv - __fold_right_assign_impl(Args &&... args) { - return __fold_right_assign_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_right_assign_impl_::__rv +__fold_right_assign_impl(Args&&... args) { + return __fold_right_assign_impl_::__impl((Args&&)args...); } // end right assign }}}2 @@ -479,31 +518,34 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr //------------------------------------------------------------------------------ // {{{2 -template struct __fold_left_assign_impl_; -template struct __fold_left_assign_impl_ { - using __rv = Arg &&; +template +struct __fold_left_assign_impl_; +template +struct __fold_left_assign_impl_ { + using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg &&arg) noexcept { return (Arg &&) arg; } + static constexpr __rv + __impl(Arg&& arg) noexcept { + return (Arg&&)arg; + } }; template struct __fold_left_assign_impl_ { - using __assign_result_t = - decltype(std::declval() = std::declval()); + using __assign_result_t = decltype(std::declval() = std::declval()); using __next_t = __fold_left_assign_impl_<__assign_result_t, Args...>; using __rv = typename __next_t::__rv; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr __rv __impl(Arg1 &&arg, Arg2 &&arg2, - Args &&... args) noexcept { - return __next_t::__impl(((Arg1 &&) arg) = (Arg2 &&) arg2, - (Args &&) args...); + static constexpr __rv + __impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + return __next_t::__impl(((Arg1&&)arg) = (Arg2&&)arg2, (Args&&)args...); } }; template -MDSPAN_FORCE_INLINE_FUNCTION constexpr - typename __fold_left_assign_impl_::__rv - __fold_left_assign_impl(Args &&... args) { - return __fold_left_assign_impl_::__impl((Args &&) args...); +MDSPAN_FORCE_INLINE_FUNCTION +constexpr typename __fold_left_assign_impl_::__rv +__fold_left_assign_impl(Args&&... args) { + return __fold_left_assign_impl_::__impl((Args&&)args...); } // end left assign }}}2 @@ -511,40 +553,27 @@ MDSPAN_FORCE_INLINE_FUNCTION constexpr #endif + template -constexpr __mdspan_enable_fold_comma -__fold_comma_impl(Args &&... args) noexcept { - return {}; -} +constexpr __mdspan_enable_fold_comma __fold_comma_impl(Args&&... args) noexcept { return { }; } -template struct __bools; +template +struct __bools; -} // namespace __fold_compatibility_impl +} // __fold_compatibility_impl } // end namespace std -#define _MDSPAN_FOLD_AND(...) \ - std::__fold_compatibility_impl::__fold_right_and_impl((__VA_ARGS__)...) -#define _MDSPAN_FOLD_OR(...) \ - std::__fold_compatibility_impl::__fold_right_or_impl((__VA_ARGS__)...) -#define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) \ - std::__fold_compatibility_impl::__fold_left_assign_impl(INIT, \ - (__VA_ARGS__)...) -#define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) \ - std::__fold_compatibility_impl::__fold_right_assign_impl((PACK)..., \ - __VA_ARGS__) -#define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) \ - std::__fold_compatibility_impl::__fold_right_times_impl((PACK)..., \ - __VA_ARGS__) -#define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) \ - std::__fold_compatibility_impl::__fold_right_plus_impl((PACK)..., __VA_ARGS__) -#define _MDSPAN_FOLD_COMMA(...) \ - std::__fold_compatibility_impl::__fold_comma_impl((__VA_ARGS__)...) - -#define _MDSPAN_FOLD_AND_TEMPLATE(...) \ - _MDSPAN_TRAIT(std::is_same, \ - __fold_compatibility_impl::__bools<(__VA_ARGS__)..., true>, \ - __fold_compatibility_impl::__bools) +# define _MDSPAN_FOLD_AND(...) std::__fold_compatibility_impl::__fold_right_and_impl((__VA_ARGS__)...) +# define _MDSPAN_FOLD_OR(...) std::__fold_compatibility_impl::__fold_right_or_impl((__VA_ARGS__)...) +# define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) std::__fold_compatibility_impl::__fold_left_assign_impl(INIT, (__VA_ARGS__)...) +# define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_assign_impl((PACK)..., __VA_ARGS__) +# define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_times_impl((PACK)..., __VA_ARGS__) +# define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_plus_impl((PACK)..., __VA_ARGS__) +# define _MDSPAN_FOLD_COMMA(...) std::__fold_compatibility_impl::__fold_comma_impl((__VA_ARGS__)...) + +# define _MDSPAN_FOLD_AND_TEMPLATE(...) \ + _MDSPAN_TRAIT(std::is_same, __fold_compatibility_impl::__bools<(__VA_ARGS__)..., true>, __fold_compatibility_impl::__bools) #endif @@ -555,9 +584,9 @@ template struct __bools; // {{{1 #if _MDSPAN_USE_VARIABLE_TEMPLATES -#define _MDSPAN_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__> +# define _MDSPAN_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__> #else -#define _MDSPAN_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value +# define _MDSPAN_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value #endif // end Variable template compatibility }}}1 @@ -567,17 +596,18 @@ template struct __bools; // {{{1 #if _MDSPAN_USE_CONSTEXPR_14 -#define _MDSPAN_CONSTEXPR_14 constexpr +# define _MDSPAN_CONSTEXPR_14 constexpr // Workaround for a bug (I think?) in EDG frontends -#ifdef __EDG__ -#define _MDSPAN_CONSTEXPR_14_DEFAULTED +# ifdef __EDG__ +# define _MDSPAN_CONSTEXPR_14_DEFAULTED +# else +# define _MDSPAN_CONSTEXPR_14_DEFAULTED constexpr +# endif #else -#define _MDSPAN_CONSTEXPR_14_DEFAULTED constexpr -#endif -#else -#define _MDSPAN_CONSTEXPR_14 -#define _MDSPAN_CONSTEXPR_14_DEFAULTED +# define _MDSPAN_CONSTEXPR_14 +# define _MDSPAN_CONSTEXPR_14_DEFAULTED #endif // end Pre-C++14 constexpr }}}1 //============================================================================== + diff --git a/src/experimental/__p0009_bits/maybe_static_value.hpp b/src/experimental/__p0009_bits/maybe_static_value.hpp new file mode 100644 index 0000000000..ffe299dc19 --- /dev/null +++ b/src/experimental/__p0009_bits/maybe_static_value.hpp @@ -0,0 +1,129 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 2.0 +// Copyright (2019) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Christian R. Trott (crtrott@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "macros.hpp" +// This is only needed for the non-standard-layout version of partially +// static array. +#if !_MDSPAN_PRESERVE_STANDARD_LAYOUT + +#include "dynamic_extent.hpp" +#include "no_unique_address.hpp" + +namespace std { +namespace experimental { + +//============================================================================== + +namespace detail { + +// static case +template +struct __maybe_static_value { + static constexpr _T __static_value = __v; + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __value() const noexcept { + return __v; + } + template + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 + __mdspan_enable_fold_comma + __set_value(_U&& __rhs) noexcept { + // Should we assert that the value matches the static value here? + return {}; + } + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __maybe_static_value() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __maybe_static_value(__maybe_static_value const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __maybe_static_value(__maybe_static_value&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __maybe_static_value& operator=(__maybe_static_value const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __maybe_static_value& operator=(__maybe_static_value&&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__maybe_static_value() noexcept = default; + + MDSPAN_INLINE_FUNCTION + constexpr explicit __maybe_static_value(_T const&) noexcept { + // Should we assert that the value matches the static value here? + } + + //-------------------------------------------------------------------------- + +}; + +// dynamic case +template +struct __maybe_static_value<_T, __is_dynamic_sentinal, __is_dynamic_sentinal, + __array_entry_index> + : __no_unique_address_emulation<_T> { + static constexpr _T __static_value = __is_dynamic_sentinal; + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __value() const noexcept { + return this->__no_unique_address_emulation<_T>::__ref(); + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept { + return this->__no_unique_address_emulation<_T>::__ref(); + } + template + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 + __mdspan_enable_fold_comma + __set_value(_U&& __rhs) noexcept { + this->__no_unique_address_emulation<_T>::__ref() = __rhs; + return {}; + } + _MDSPAN_NO_UNIQUE_ADDRESS _T __v = {}; +}; + +} // namespace detail + +//============================================================================== + +} // end namespace experimental +} // end namespace std + +#endif // !_MDSPAN_PRESERVE_STANDARD_LAYOUT diff --git a/src/experimental/__p0009_bits/mixed_size_storage.hpp b/src/experimental/__p0009_bits/mixed_size_storage.hpp deleted file mode 100644 index c95bb3dc9f..0000000000 --- a/src/experimental/__p0009_bits/mixed_size_storage.hpp +++ /dev/null @@ -1,241 +0,0 @@ -/* -//@HEADER -// ************************************************************************ -// -// Kokkos v. 2.0 -// Copyright (2019) Sandia Corporation -// -// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, -// the U.S. Government retains certain rights in this software. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the Corporation nor the names of the -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Questions? Contact Christian R. Trott (crtrott@sandia.gov) -// -// ************************************************************************ -//@HEADER -*/ - -#pragma once - -#include "array_workaround.hpp" -#include "dynamic_extent.hpp" -#include "trait_backports.hpp" - -#include -#include // ptrdiff_t -#include // integer_sequence - -namespace std { -namespace experimental { -namespace detail { - -_MDSPAN_INLINE_VARIABLE constexpr struct - construct_mixed_storage_from_sizes_tag_t { -} construct_mixed_storage_from_sizes_tag = {}; - -template > -class mixed_static_and_dynamic_size_storage; - -template -class mixed_static_and_dynamic_size_storage< - integer_sequence, - integer_sequence, - integer_sequence> { -public: - static constexpr auto size_dynamic = _MDSPAN_FOLD_PLUS_RIGHT( - static_cast((Sizes == dynamic_extent)), /* + ... + */ 0); - -private: - _MDSPAN_NO_UNIQUE_ADDRESS __array_workaround::__array - dynamic_sizes = {}; - - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t _select(true_type) const - noexcept { - return dynamic_sizes.template __get_n(); - } - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t _select(false_type) const - noexcept { - return Size; - } - - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 ptrdiff_t - _select_set(true_type, ptrdiff_t value) noexcept { - dynamic_sizes.template __set_n(value); - return 0; - } - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 ptrdiff_t - _select_set(false_type, ptrdiff_t) noexcept { - return 0; - } - -public: - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t select() const noexcept { - return _select( - integral_constant{}); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t select_n() const noexcept { - return Idx == N ? _select( - integral_constant{}) - : Default; - } - - template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ptrdiff_t - select_static() noexcept { - return Size == dynamic_extent ? Default : Size; - } - - template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ptrdiff_t - select_static_n() noexcept { - return (Idx == N) ? ((Size == dynamic_extent) ? Default : Size) - : DefaultWrongIdx; - } - - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 ptrdiff_t - select_set(ptrdiff_t value) noexcept { - return _select_set( - integral_constant < bool, Size == dynamic_extent && Idx == N > {}, - value); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION constexpr ptrdiff_t get() const noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT( - (select_n()), /* + ... + */ 0); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION static constexpr ptrdiff_t - get_static() noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT( - (select_static_n()), - /* + ... + */ 0); - } - - MDSPAN_FORCE_INLINE_FUNCTION - constexpr ptrdiff_t get(size_t n) const noexcept { - return _MDSPAN_FOLD_PLUS_RIGHT( - ((Idxs == n) ? select() : 0), /* + ... + */ 0); - } - - template - MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __mdspan_enable_fold_comma - set(ptrdiff_t value) noexcept { - _MDSPAN_FOLD_COMMA( - select_set(value) /* , ... */); - return {}; - } - - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr mixed_static_and_dynamic_size_storage() = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr mixed_static_and_dynamic_size_storage( - mixed_static_and_dynamic_size_storage const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr mixed_static_and_dynamic_size_storage( - mixed_static_and_dynamic_size_storage &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED mixed_static_and_dynamic_size_storage & - operator=(mixed_static_and_dynamic_size_storage const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - _MDSPAN_CONSTEXPR_14_DEFAULTED mixed_static_and_dynamic_size_storage & - operator=(mixed_static_and_dynamic_size_storage &&) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED - ~mixed_static_and_dynamic_size_storage() noexcept = default; - - template - MDSPAN_INLINE_FUNCTION constexpr mixed_static_and_dynamic_size_storage( - construct_mixed_storage_from_sizes_tag_t, Integral... dyn_sizes) -#if (defined(_MSC_VER) && !defined(_WIN64)) - : dynamic_sizes(ptrdiff_t{static_cast(dyn_sizes)}...) -#else - : dynamic_sizes(ptrdiff_t{dyn_sizes}...) -#endif - { - } - - template - MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 - mixed_static_and_dynamic_size_storage( - mixed_static_and_dynamic_size_storage< - std::integer_sequence, - std::integer_sequence, - std::integer_sequence> const &other) - : dynamic_sizes() { - _MDSPAN_FOLD_COMMA(set(other.template get()) /* , ... */); - } - - template - MDSPAN_INLINE_FUNCTION constexpr mixed_static_and_dynamic_size_storage( - std::array const &dyn) - : dynamic_sizes(dyn) {} -}; - -//================================================================================ - -template struct _make_mixed_impl_helper; -template -struct _make_mixed_impl_helper, - integer_sequence> { - static constexpr ptrdiff_t value = _MDSPAN_FOLD_PLUS_RIGHT( - (int(Idxs < size_t(N) && Sizes == dynamic_extent)), /* + ... + */ 0); -}; - -template struct _make_mixed_impl; -template -struct _make_mixed_impl, void> - : _make_mixed_impl, - std::make_index_sequence> {}; -template -struct _make_mixed_impl, - integer_sequence> { - using type = mixed_static_and_dynamic_size_storage< - integer_sequence, - integer_sequence, - std::integer_sequence< - ptrdiff_t, Sizes...>>::value...>>; -}; - -} // namespace detail -} // end namespace experimental -} // namespace std diff --git a/src/experimental/__p0009_bits/no_unique_address.hpp b/src/experimental/__p0009_bits/no_unique_address.hpp new file mode 100644 index 0000000000..f509cd7990 --- /dev/null +++ b/src/experimental/__p0009_bits/no_unique_address.hpp @@ -0,0 +1,272 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 2.0 +// Copyright (2019) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Christian R. Trott (crtrott@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#pragma once + +#include "macros.hpp" + +#include "trait_backports.hpp" + +namespace std { +namespace experimental { +namespace detail { + +//============================================================================== + +template +struct __no_unique_address_emulation { + using __stored_type = _T; + _T __v; + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept { + return __v; + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept { + return __v; + } +}; + +// Empty case +// This doesn't work if _T is final, of course, but we're not using anything +// like that currently. That kind of thing could be added pretty easily though +template +struct __no_unique_address_emulation< + _T, _Disambiguator, + enable_if_t<_MDSPAN_TRAIT(is_empty, _T) && + // If the type isn't trivially destructible, its destructor + // won't be called at the right time, so don't use this + // specialization + _MDSPAN_TRAIT(is_trivially_destructible, _T)>> : private _T { + using __stored_type = _T; + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept { + return *static_cast<_T const *>(this); + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept { + return *static_cast<_T *>(this); + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __no_unique_address_emulation() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __no_unique_address_emulation( + __no_unique_address_emulation const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __no_unique_address_emulation( + __no_unique_address_emulation &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation & + operator=(__no_unique_address_emulation const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation & + operator=(__no_unique_address_emulation &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__no_unique_address_emulation() noexcept = default; + + // Explicitly make this not a reference so that the copy or move + // constructor still gets called. + MDSPAN_INLINE_FUNCTION + explicit constexpr __no_unique_address_emulation(_T const& __v) noexcept : _T(__v) {} + MDSPAN_INLINE_FUNCTION + explicit constexpr __no_unique_address_emulation(_T&& __v) noexcept : _T(::std::move(__v)) {} +}; + +//============================================================================== + +// TODO also check for final? + +// Neither empty +template struct __compressed_pair { + _T __t_val; + _U __u_val; + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__first() noexcept { return __t_val; } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__first() const noexcept { + return __t_val; + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _U &__second() noexcept { return __u_val; } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _U const &__second() const noexcept { + return __u_val; + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__compressed_pair() noexcept = default; + template + MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_TLike &&__t, _ULike &&__u) + : __t_val((_TLike &&) __t), __u_val((_ULike &&) __u) {} +}; + +// First empty +template +struct __compressed_pair< + _T, _U, + enable_if_t<_MDSPAN_TRAIT(is_empty, _T) && !_MDSPAN_TRAIT(is_empty, _U)>> + : private _T { + _U __u_val; + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__first() noexcept { + return *static_cast<_T *>(this); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__first() const noexcept { + return *static_cast<_T const *>(this); + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _U &__second() noexcept { return __u_val; } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _U const &__second() const noexcept { + return __u_val; + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__compressed_pair() noexcept = default; + template + MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_TLike &&__t, _ULike &&__u) + : _T((_TLike &&) __t), __u_val((_ULike &&) __u) {} +}; + +// Second empty +template +struct __compressed_pair< + _T, _U, + enable_if_t<_MDSPAN_TRAIT(is_empty, _U) && !_MDSPAN_TRAIT(is_empty, _T)>> + : private _U { + _T __t_val; + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__first() noexcept { return __t_val; } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__first() const noexcept { + return __t_val; + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _U &__second() noexcept { + return *static_cast<_U *>(this); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _U const &__second() const noexcept { + return *static_cast<_U const *>(this); + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__compressed_pair() noexcept = default; + + template + MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_TLike &&__t, _ULike &&__u) + : _U((_ULike &&) __u), __t_val((_TLike &&) __t) {} +}; + +// Both empty +template +struct __compressed_pair< + _T, _U, + enable_if_t<_MDSPAN_TRAIT(is_empty, _T) && _MDSPAN_TRAIT(is_empty, _U)>> + // We need to use the __no_unique_address_emulation wrapper here to avoid + // base class ambiguities. + : private __no_unique_address_emulation<_T, 0>, + private __no_unique_address_emulation<_U, 1> { + using __first_base_t = __no_unique_address_emulation<_T, 0>; + using __second_base_t = __no_unique_address_emulation<_U, 1>; + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__first() noexcept { + return this->__first_base_t::__ref(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__first() const noexcept { + return this->__first_base_t::__ref(); + } + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _U &__second() noexcept { + return this->__second_base_t::__ref(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _U const &__second() const noexcept { + return this->__second_base_t::__ref(); + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __compressed_pair(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & + operator=(__compressed_pair &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__compressed_pair() noexcept = default; + template + MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_TLike &&__t, _ULike &&__u) noexcept + : __first_base_t(_T((_TLike &&) __t)), + __second_base_t(_U((_ULike &&) __u)) {} +}; + +} // namespace detail + +//============================================================================== + +} // end namespace experimental +} // end namespace std \ No newline at end of file diff --git a/src/experimental/__p0009_bits/standard_layout_static_array.hpp b/src/experimental/__p0009_bits/standard_layout_static_array.hpp new file mode 100644 index 0000000000..aa9a8be5f0 --- /dev/null +++ b/src/experimental/__p0009_bits/standard_layout_static_array.hpp @@ -0,0 +1,501 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 2.0 +// Copyright (2019) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Christian R. Trott (crtrott@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#pragma once + +#include "macros.hpp" +#include "no_unique_address.hpp" +#include "trait_backports.hpp" // enable_if + +#include +#include // integer_sequence +#include + +namespace std { +namespace experimental { +namespace detail { + +//============================================================================== + +_MDSPAN_INLINE_VARIABLE constexpr struct + __construct_partially_static_array_from_sizes_tag_t { +} __construct_partially_static_array_from_sizes_tag = {}; + +template struct __construct_psa_from_dynamic_values_tag_t {}; + +//============================================================================== + +template using __repeated_with_idxs = _T; + +//============================================================================== + +#if _MDSPAN_PRESERVE_STANDARD_LAYOUT + +/** + * PSA = "partially static array" + * + * @tparam _T + * @tparam _ValsSeq + * @tparam __sentinal + */ +template > +struct __standard_layout_psa; + +//============================================================================== + +// Static case +template +struct __standard_layout_psa< + _Tag, _T, integer_sequence<_T, __value, __values_or_sentinals...>, + __sentinal, integer_sequence> + : private __no_unique_address_emulation<__standard_layout_psa< + _Tag, _T, integer_sequence<_T, __values_or_sentinals...>, __sentinal, + integer_sequence>> { + //-------------------------------------------------------------------------- + + using __next_t = + __standard_layout_psa<_Tag, _T, + integer_sequence<_T, __values_or_sentinals...>, + __sentinal, integer_sequence>; + using __base_t = __no_unique_address_emulation<__next_t>; + + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __next_t &__next() noexcept { + return this->__base_t::__ref(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr __next_t const &__next() const noexcept { + return this->__base_t::__ref(); + } + + static constexpr auto __size = sizeof...(_Idxs) + 1; +#ifdef _MSC_VER + // MSVC doesn't like the fact that __next_t happens to be a base + // class that's private, even though __size_synamic is public in + // it's definition. + struct __msvc_workaround_tag {}; + using __msvc_workaround_next_t = __standard_layout_psa< + __msvc_workaround_tag, _T, + integer_sequence<_T, __values_or_sentinals...>, __sentinal, + integer_sequence>; + static constexpr auto __size_dynamic = + __msvc_workaround_next_t::__size_dynamic; +#else + static constexpr auto __size_dynamic = __next_t::__size_dynamic; +#endif + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = + default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__standard_layout_psa() noexcept = default; + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION + constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t, _T const &__val, + __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept + : __base_t(__base_t{__next_t( + __construct_partially_static_array_from_sizes_tag, __vals...)}) {} + + // Dynamic idxs only given version, which is probably going to not need to + // supported by the time mdspan is merged into the standard, but is currently + // the way this is specified. Use a repeated tag for the old semantics + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t, + __construct_partially_static_array_from_sizes_tag_t, + _Ts const &... __vals) noexcept + : __base_t(__base_t{__next_t( + __construct_partially_static_array_from_sizes_tag, + __construct_partially_static_array_from_sizes_tag, __vals...)}) {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + array<_T, _N> const &__vals) noexcept + : __base_t(__base_t{__next_t(__vals)}) {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + __construct_psa_from_dynamic_values_tag_t<_IDynamic> __tag, + array<_T, _NDynamic> const &__vals) noexcept + : __base_t(__base_t{__next_t(__tag, __vals)}) {} + + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __standard_layout_psa<_UTag, _U, _UValsSeq, __u_sentinal, _IdxsSeq> const + &__rhs) noexcept + : __base_t(__base_t{__next_t(__rhs.__next())}) {} + + //-------------------------------------------------------------------------- + + // See https://godbolt.org/z/_KSDNX for a summary-by-example of why this is + // necessary. The we're using inheritance here instead of an alias template + // is because we have to deduce __values_or_sentinals in several places, and + // alias templates doen't permit that in this context. + MDSPAN_FORCE_INLINE_FUNCTION + constexpr __standard_layout_psa const &__enable_psa_conversion() const + noexcept { + return *this; + } + + template = 0> + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { + return this->__base_t::__ref().template __get_n<_I>(); + } + template = 1> + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { + return __value; + } + template = 0> + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void + __set_n(_T const &__rhs) noexcept { + this->__base_t::__ref().__set_value(__rhs); + } + template = 1> + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void + __set_n(_T const &__rhs) noexcept { + // Don't assert here because that would break constexpr. This better + // not change anything, though + } + template = __sentinal> + MDSPAN_FORCE_INLINE_FUNCTION static constexpr _T __get_static_n() noexcept { + return __value; + } + template __default = __sentinal> + MDSPAN_FORCE_INLINE_FUNCTION static constexpr _T __get_static_n() noexcept { + return __next_t::template __get_static_n<_I, __default>(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t __n) const noexcept { + return __value * (_T(_Idx == __n)) + this->__base_t::__ref().__get(__n); + } + + //-------------------------------------------------------------------------- +}; + +//============================================================================== + +// Dynamic case, __next_t may or may not be empty +template +struct __standard_layout_psa< + _Tag, _T, integer_sequence<_T, __sentinal, __values_or_sentinals...>, + __sentinal, integer_sequence> { + //-------------------------------------------------------------------------- + + using __next_t = + __standard_layout_psa<_Tag, _T, + integer_sequence<_T, __values_or_sentinals...>, + __sentinal, integer_sequence>; + + using __value_pair_t = __compressed_pair<_T, __next_t>; + __value_pair_t __value_pair; + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __next_t &__next() noexcept { + return __value_pair.__second(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr __next_t const &__next() const noexcept { + return __value_pair.__second(); + } + + static constexpr auto __size = sizeof...(_Idxs) + 1; + static constexpr auto __size_dynamic = 1 + __next_t::__size_dynamic; + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = + default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__standard_layout_psa() noexcept = default; + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION + constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t, _T const &__val, + __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept + : __value_pair(__val, + __next_t(__construct_partially_static_array_from_sizes_tag, + __vals...)) {} + + // Dynamic idxs only given version, which is probably going to not need to + // supported by the time mdspan is merged into the standard, but is currently + // the way this is specified. Use a repeated tag for the old semantics + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t, + __construct_partially_static_array_from_sizes_tag_t, _T const &__val, + _Ts const &... __vals) noexcept + : __value_pair(__val, + __next_t(__construct_partially_static_array_from_sizes_tag, + __construct_partially_static_array_from_sizes_tag, + __vals...)) {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + array<_T, _N> const &__vals) noexcept + : __value_pair(::std::get<_Idx>(__vals), __vals) {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + __construct_psa_from_dynamic_values_tag_t<_IDynamic> __tag, + array<_T, _NDynamic> const &__vals) noexcept + : __value_pair( + ::std::get<_IDynamic>(__vals), + __next_t(__construct_psa_from_dynamic_values_tag_t<_IDynamic + 1>{}, + __vals)) {} + + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __standard_layout_psa<_UTag, _U, _UValsSeq, __u_sentinal, _UIdxsSeq> const + &__rhs) noexcept + : __value_pair(__rhs.template __get_n<_Idx>(), __rhs.__next()) {} + + //-------------------------------------------------------------------------- + + // See comment in the previous partial specialization for why this is + // necessary. Or just trust me that it's messy. + MDSPAN_FORCE_INLINE_FUNCTION + constexpr __standard_layout_psa const &__enable_psa_conversion() const + noexcept { + return *this; + } + + template = 0> + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { + return __next().template __get_n<_I>(); + } + template = 1> + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { + return __value_pair.__first(); + } + template = 0> + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void + __set_n(_T const &__rhs) noexcept { + __next().__set_value(__rhs); + } + template = 1> + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void + __set_n(_T const &__rhs) noexcept { + __value_pair.__first() = __rhs; + } + template __default = __sentinal> + MDSPAN_FORCE_INLINE_FUNCTION static constexpr _T __get_static_n() noexcept { + return __default; + } + template __default = __sentinal> + MDSPAN_FORCE_INLINE_FUNCTION static constexpr _T __get_static_n() noexcept { + return __next_t::template __get_static_n<_I, __default>(); + } + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t __n) const noexcept { + return __value_pair.__first() * (_T(_Idx == __n)) + __next().__get(__n); + } + + //-------------------------------------------------------------------------- +}; + +// empty/terminal case +template +struct __standard_layout_psa<_Tag, _T, integer_sequence<_T>, __sentinal, + integer_sequence> { + //-------------------------------------------------------------------------- + + static constexpr auto __size = 0; + static constexpr auto __size_dynamic = 0; + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa() noexcept +#if defined(__clang__) || defined(_MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND) + // As far as I can tell, there appears to be a bug in clang that's causing + // this to be non-constexpr when it's defaulted. + { } +#else + = default; +#endif + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa const &) noexcept = + default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __standard_layout_psa(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __standard_layout_psa & + operator=(__standard_layout_psa &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__standard_layout_psa() noexcept = default; + + MDSPAN_INLINE_FUNCTION + constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t) noexcept {} + + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __construct_partially_static_array_from_sizes_tag_t, + __construct_partially_static_array_from_sizes_tag_t) noexcept {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + array<_T, _N> const &) noexcept {} + + template + MDSPAN_INLINE_FUNCTION constexpr explicit __standard_layout_psa( + __construct_psa_from_dynamic_values_tag_t<_IDynamic> __tag, + array<_T, _NDynamic> const &) noexcept {} + + template + MDSPAN_INLINE_FUNCTION constexpr __standard_layout_psa( + __standard_layout_psa<_UTag, _U, _UValsSeq, __u_sentinal, _UIdxsSeq> const&) noexcept {} + + // See comment in the previous partial specialization for why this is + // necessary. Or just trust me that it's messy. + MDSPAN_FORCE_INLINE_FUNCTION + constexpr __standard_layout_psa const &__enable_psa_conversion() const + noexcept { + return *this; + } + + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get(size_t /*n*/) const noexcept { + return 0; + } +}; + +// Same thing, but with a disambiguator so that same-base issues doesn't cause +// a loss of standard-layout-ness. +template +struct __partially_static_sizes_tagged + : __standard_layout_psa< + _Tag, ptrdiff_t, + integer_sequence> { + using __tag_t = _Tag; + using __psa_impl_t = __standard_layout_psa< + _Tag, ptrdiff_t, integer_sequence>; + using __psa_impl_t::__psa_impl_t; + MDSPAN_INLINE_FUNCTION + constexpr __partially_static_sizes_tagged() noexcept +#ifdef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND + : __psa_impl_t() { } +#else + = default; +#endif + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __partially_static_sizes_tagged( + __partially_static_sizes_tagged const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __partially_static_sizes_tagged( + __partially_static_sizes_tagged &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_sizes_tagged & + operator=(__partially_static_sizes_tagged const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_sizes_tagged & + operator=(__partially_static_sizes_tagged &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__partially_static_sizes_tagged() noexcept = default; + + template + MDSPAN_FORCE_INLINE_FUNCTION constexpr explicit __partially_static_sizes_tagged( + __partially_static_sizes_tagged<_UTag, __values_or_sentinals...> const& __vals + ) noexcept : __psa_impl_t(__vals.__enable_psa_conversion()) { } +}; + +struct __no_tag {}; +template +struct __partially_static_sizes + : __partially_static_sizes_tagged<__no_tag, __values_or_sentinals...> { +private: + using __base_t = + __partially_static_sizes_tagged<__no_tag, __values_or_sentinals...>; + template + MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes( + __partially_static_sizes_tagged<_UTag, __values_or_sentinals...>&& __vals + ) noexcept : __base_t(::std::move(__vals)) { } +public: + using __base_t::__base_t; + +#ifdef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND + MDSPAN_INLINE_FUNCTION + constexpr __partially_static_sizes() noexcept : __base_t() { } +#endif + template + MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes_tagged< + _UTag, __values_or_sentinals...> + __with_tag() const noexcept { + return __partially_static_sizes_tagged<_UTag, __values_or_sentinals...>(*this); + } +}; + +#endif // _MDSPAN_PRESERVE_STATIC_LAYOUT + +} // namespace detail +} // end namespace experimental +} // namespace std diff --git a/src/experimental/__p0009_bits/static_array.hpp b/src/experimental/__p0009_bits/static_array.hpp new file mode 100644 index 0000000000..0d3d08a403 --- /dev/null +++ b/src/experimental/__p0009_bits/static_array.hpp @@ -0,0 +1,288 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 2.0 +// Copyright (2019) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Christian R. Trott (crtrott@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#pragma once + +#include "macros.hpp" +#if !_MDSPAN_PRESERVE_STANDARD_LAYOUT + +#include "dynamic_extent.hpp" +#include "trait_backports.hpp" +#include "maybe_static_value.hpp" +#include "standard_layout_static_array.hpp" +#include "type_list.hpp" + +#include // ptrdiff_t +#include // integer_sequence +#include + +namespace std { +namespace experimental { +namespace detail { + +//============================================================================== + +template struct __mask_element {}; + +template +struct __mask_sequence_assign_op { + template <_T _V> + __mask_sequence_assign_op<_T, _Result..., _V> + operator=(__mask_element<_T, _V, true>&&); + template <_T _V> + __mask_sequence_assign_op<_T, _Result...> + operator=(__mask_element<_T, _V, false>&&); + using __result = integer_sequence<_T, _Result...>; +}; + +template +struct __mask_sequence; + +template +struct __mask_sequence, integer_sequence> +{ + using type = typename decltype( + _MDSPAN_FOLD_ASSIGN_LEFT( + __mask_sequence_assign_op<_T>{}, /* = ... = */ __mask_element<_T, _Vals, _Masks>{} + ) + )::__result; +}; + +//============================================================================== + +template +class __partially_static_array_impl; + +template < + class _T, _T... __values_or_sentinals, _T __sentinal, + size_t... _Idxs, + size_t... _IdxsDynamic, + size_t... _IdxsDynamicIdxs +> +class __partially_static_array_impl< + _T, + integer_sequence<_T, __values_or_sentinals...>, + __sentinal, + integer_sequence, + integer_sequence, + integer_sequence +> + : private __maybe_static_value<_T, __values_or_sentinals, __sentinal, + _Idxs>... { +private: + + template + using __base_n = typename __type_at<_N, + __type_list<__maybe_static_value<_T, __values_or_sentinals, __sentinal, _Idxs>...> + >::type; + +public: + + static constexpr auto __size = sizeof...(_Idxs); + static constexpr auto __size_dynamic = + _MDSPAN_FOLD_PLUS_RIGHT(static_cast((__values_or_sentinals == __sentinal)), /* + ... + */ 0); + + //-------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __partially_static_array_impl() = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __partially_static_array_impl( + __partially_static_array_impl const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + constexpr __partially_static_array_impl( + __partially_static_array_impl &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_array_impl & + operator=(__partially_static_array_impl const &) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + _MDSPAN_CONSTEXPR_14_DEFAULTED __partially_static_array_impl & + operator=(__partially_static_array_impl &&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED + ~__partially_static_array_impl() noexcept = default; + + MDSPAN_INLINE_FUNCTION + constexpr __partially_static_array_impl( + __construct_partially_static_array_from_sizes_tag_t, + __repeated_with_idxs<_Idxs, _T> const &... __vals) noexcept + : __base_n<_Idxs>(__base_n<_Idxs>{{__vals}})... {} + + // Dynamic idxs only given version, which is probably going to not need to + // supported by the time mdspan is merged into the standard, but is currently the + // way this is specified. Use a repeated tag for the old semantics + MDSPAN_INLINE_FUNCTION + constexpr __partially_static_array_impl( + __construct_partially_static_array_from_sizes_tag_t, + __construct_partially_static_array_from_sizes_tag_t, + __repeated_with_idxs<_IdxsDynamicIdxs, _T> const &... __vals) noexcept + : __base_n<_IdxsDynamic>(__base_n<_IdxsDynamic>{{__vals}})... {} + + MDSPAN_INLINE_FUNCTION constexpr explicit __partially_static_array_impl( + array<_T, sizeof...(_Idxs)> const& __vals) noexcept + : __partially_static_array_impl( + __construct_partially_static_array_from_sizes_tag, + ::std::get<_Idxs>(__vals)...) {} + + // clang-format off + MDSPAN_FUNCTION_REQUIRES( + (MDSPAN_INLINE_FUNCTION constexpr explicit), + __partially_static_array_impl, + (array<_T, __size_dynamic> const &__vals), noexcept, + /* requires */ + (sizeof...(_Idxs) != __size_dynamic) + ): __partially_static_array_impl( + __construct_partially_static_array_from_sizes_tag, + __construct_partially_static_array_from_sizes_tag, + ::std::get<_IdxsDynamicIdxs>(__vals)...) {} + // clang-format on + + template + MDSPAN_INLINE_FUNCTION constexpr __partially_static_array_impl( + __partially_static_array_impl< + _U, _UValsSeq, __u_sentinal, _UIdxsSeq, + _UIdxsDynamicSeq, _UIdxsDynamicIdxsSeq> const &__rhs) noexcept + : __partially_static_array_impl( + __construct_partially_static_array_from_sizes_tag, + __rhs.template __get_n<_Idxs>()...) {} + + //-------------------------------------------------------------------------- + + // See comment in the previous partial specialization for why this is + // necessary. Or just trust me that it's messy. + MDSPAN_FORCE_INLINE_FUNCTION + constexpr __partially_static_array_impl const &__enable_psa_conversion() const + noexcept { + return *this; + } + + template + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T __get_n() const noexcept { + return static_cast<__base_n<_I> const*>(this)->__value(); + } + + template + MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 void __set_n(_U&& __rhs) noexcept { + static_cast<__base_n<_I>*>(this)->__set_value((_U&&)__rhs); + } + + template + MDSPAN_FORCE_INLINE_FUNCTION static constexpr _T + __get_static_n() noexcept { + return __base_n<_I>::__static_value == __sentinal ? + __default : __base_n<_I>::__static_value; + } + + MDSPAN_FORCE_INLINE_FUNCTION constexpr _T + __get(size_t __n) const noexcept { + return _MDSPAN_FOLD_PLUS_RIGHT( + (_T(_Idxs == __n) * __get_n<_Idxs>()), /* + ... + */ _T(0) + ); + } + +}; + +//============================================================================== + +template > +struct __partially_static_array_impl_maker; + +template < + class _T, _T... _Vals, _T __sentinal, size_t... _Idxs +> +struct __partially_static_array_impl_maker< + _T, integer_sequence<_T, _Vals...>, __sentinal, integer_sequence +> +{ + using __dynamic_idxs = typename __mask_sequence< + integer_sequence, + integer_sequence + >::type; + using __impl_base = + __partially_static_array_impl<_T, + integer_sequence<_T, _Vals...>, + __sentinal, integer_sequence, + __dynamic_idxs, + make_index_sequence<__dynamic_idxs::size()> + >; +}; + +template +class __partially_static_array_with_sentinal + : public __partially_static_array_impl_maker<_T, _ValsSeq, __sentinal>::__impl_base +{ +private: + using __base_t = typename __partially_static_array_impl_maker<_T, _ValsSeq, __sentinal>::__impl_base; +public: + using __base_t::__base_t; +}; + +//============================================================================== + +template +struct __partially_static_sizes : + __partially_static_array_with_sentinal< + ptrdiff_t, ::std::integer_sequence> +{ +private: + using __base_t = __partially_static_array_with_sentinal< + ptrdiff_t, ::std::integer_sequence>; +public: + using __base_t::__base_t; + template + MDSPAN_FORCE_INLINE_FUNCTION constexpr __partially_static_sizes<__values_or_sentinals...> + __with_tag() const noexcept { + return *this; + } +}; + +// Tags are needed for the standard layout version, but not here +template +using __partially_static_sizes_tagged = __partially_static_sizes<__values_or_sentinals...>; + +} // namespace detail +} // end namespace experimental +} // namespace std + +#endif // !_MDSPAN_PRESERVE_STANDARD_LAYOUT diff --git a/src/experimental/__p0009_bits/subspan.hpp b/src/experimental/__p0009_bits/subspan.hpp index 483a4740e2..dc0a6f334a 100644 --- a/src/experimental/__p0009_bits/subspan.hpp +++ b/src/experimental/__p0009_bits/subspan.hpp @@ -41,11 +41,11 @@ //@HEADER */ + #pragma once -#include "all_type.hpp" -#include "array_workaround.hpp" #include "basic_mdspan.hpp" +#include "all_type.hpp" #include "dynamic_extent.hpp" #include "layout_left.hpp" #include "layout_right.hpp" @@ -53,7 +53,7 @@ #include "macros.hpp" #include "trait_backports.hpp" -#include // std::apply +#include // std::apply #include // std::pair namespace std { @@ -71,81 +71,96 @@ struct _slice_wrap { //-------------------------------------------------------------------------------- template -MDSPAN_INLINE_FUNCTION _slice_wrap -_wrap_slice(ptrdiff_t val, ptrdiff_t ext, ptrdiff_t stride) { - return {val, ext, stride}; -} +MDSPAN_INLINE_FUNCTION constexpr +_slice_wrap +_wrap_slice(ptrdiff_t val, ptrdiff_t ext, ptrdiff_t stride) { return { val, ext, stride }; } template -MDSPAN_INLINE_FUNCTION _slice_wrap -_wrap_slice(all_type val, ptrdiff_t ext, ptrdiff_t stride) { - return {val, ext, stride}; -} +MDSPAN_INLINE_FUNCTION constexpr +_slice_wrap +_wrap_slice(all_type val, ptrdiff_t ext, ptrdiff_t stride) { return { val, ext, stride }; } // TODO generalize this to anything that works with std::get<0> and std::get<1> template -MDSPAN_INLINE_FUNCTION - _slice_wrap> - _wrap_slice(std::pair const &val, ptrdiff_t ext, - ptrdiff_t stride) { - return {val, ext, stride}; +MDSPAN_INLINE_FUNCTION constexpr +_slice_wrap> +_wrap_slice(std::pair const& val, ptrdiff_t ext, ptrdiff_t stride) +{ + return { val, ext, stride }; } //-------------------------------------------------------------------------------- -template -struct preserve_layout_right_analysis : std::integral_constant { + +template < + bool result=true, + bool encountered_first_all=false, + bool encountered_first_pair=false +> +struct preserve_layout_right_analysis : integral_constant { using layout_type_if_preserved = layout_right; using encounter_pair = preserve_layout_right_analysis< - // If the pair isn't the right-most slice (i.e., if there was a previous pair), - // we can't preserve any contiguous layout. Nothing else should matter - (encountered_first_pair ? false : result), - // Whether or not we've encountered the first all doesn't change, though it - // doesn't really matter, since anything to the right of this leads to a false - // result - encountered_first_all, - // This is a pair, so we've encountered at least one - true>; + // If the pair isn't the right-most slice (i.e., if there was a previous pair), + // we can't preserve any contiguous layout. Nothing else should matter + (encountered_first_pair ? false : result), + // Whether or not we've encountered the first all doesn't change, though it + // doesn't really matter, since anything to the right of this leads to a false + // result + encountered_first_all, + // This is a pair, so we've encountered at least one + true + >; using encounter_all = preserve_layout_right_analysis< - // encountering an all changes nothing unless we've already encountered a pair - (encountered_first_pair ? false : result), - // This is an all, so we've encountered at least one - true, - // nothing changes about this last one - encountered_first_pair>; + // encountering an all changes nothing unless we've already encountered a pair + (encountered_first_pair ? false : result), + // This is an all, so we've encountered at least one + true, + // nothing changes about this last one + encountered_first_pair + >; using encounter_scalar = preserve_layout_right_analysis< - // if there's a scalar to the right of any non-scalar slice, we can't preserve - // any contiguous layout: - (encountered_first_all || encountered_first_pair) ? false : result, - // nothing else changes (though if they're true, it doesn't matter) - encountered_first_all, encountered_first_pair>; + // if there's a scalar to the right of any non-scalar slice, we can't preserve + // any contiguous layout: + (encountered_first_all || encountered_first_pair) ? false : result, + // nothing else changes (though if they're true, it doesn't matter) + encountered_first_all, + encountered_first_pair + >; }; -template -struct preserve_layout_left_analysis : std::integral_constant { +template < + bool result=true, + bool encountered_first_scalar=false, + bool encountered_first_all=false, + bool encountered_first_pair=false +> +struct preserve_layout_left_analysis : integral_constant { using layout_type_if_preserved = layout_left; using encounter_pair = preserve_layout_left_analysis< - // Only the left-most slice can be a pair. If we've encountered anything else, - // we can't preserve any contiguous layout - (encountered_first_scalar || encountered_first_all || - encountered_first_pair) - ? false - : result, - // These change in the expected ways - encountered_first_scalar, encountered_first_all, true>; + // Only the left-most slice can be a pair. If we've encountered anything else, + // we can't preserve any contiguous layout + (encountered_first_scalar || encountered_first_all || encountered_first_pair) ? false : result, + // These change in the expected ways + encountered_first_scalar, + encountered_first_all, + true + >; using encounter_all = preserve_layout_left_analysis< - // If there's a scalar to the left of us, we can't preserve contiguous - encountered_first_scalar ? false : result, - // These change in the expected ways - encountered_first_scalar, true, encountered_first_pair>; + // If there's a scalar to the left of us, we can't preserve contiguous + encountered_first_scalar ? false : result, + // These change in the expected ways + encountered_first_scalar, + true, + encountered_first_pair + >; using encounter_scalar = preserve_layout_left_analysis< - // If there's a scalar to the left of us, we can't preserve contiguous - result, - // These change in the expected ways - true, encountered_first_all, encountered_first_pair>; + // If there's a scalar to the left of us, we can't preserve contiguous + result, + // These change in the expected ways + true, + encountered_first_all, + encountered_first_pair + >; }; struct ignore_layout_preservation : std::integral_constant { @@ -155,252 +170,250 @@ struct ignore_layout_preservation : std::integral_constant { using encounter_scalar = ignore_layout_preservation; }; +template +struct preserve_layout_analysis + : ignore_layout_preservation { }; +template <> +struct preserve_layout_analysis + : preserve_layout_right_analysis<> { }; +template <> +struct preserve_layout_analysis + : preserve_layout_left_analysis<> { }; + //-------------------------------------------------------------------------------- -template , - class ExtentInitializers = __array_workaround::__array, - class DynamicStrides = __array_workaround::__array, - class = std::make_index_sequence, - class = std::make_index_sequence, - class = std::make_index_sequence> -struct _assign_op_slice_handler; - -template -struct _assign_op_slice_handler< - integer_sequence, - integer_sequence, PreserveLayoutAnalysis, - __array_workaround::__array, - __array_workaround::__array, - __array_workaround::__array, - integer_sequence, - integer_sequence, - integer_sequence> { - static_assert(_MDSPAN_FOLD_AND((StaticStrides == dynamic_extent || - StaticStrides > 0) /* && ... */), - " "); - - __array_workaround::__array offsets = {}; - __array_workaround::__array dynamic_extents = {}; - __array_workaround::__array dynamic_strides = {}; - - // Some old compilers don't like aggregate initialization, so we have to do this. It shouldn't hurt other compilers -#if !MDSPAN_HAS_CXX_14 - MDSPAN_INLINE_FUNCTION - _assign_op_slice_handler( - __array_workaround::__array arg_offsets, - __array_workaround::__array - arg_dynamic_extents, - __array_workaround::__array - arg_dynamic_strides) noexcept - : offsets(std::move(arg_offsets)), - dynamic_extents(std::move(arg_dynamic_extents)), - dynamic_strides(std::move(arg_dynamic_strides)) {} - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler() noexcept = - default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler( - _assign_op_slice_handler const &) noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler( - _assign_op_slice_handler &&) noexcept = default; +template < + class _PreserveLayoutAnalysis, + class _OffsetsArray=__partially_static_sizes<>, + class _ExtsArray=__partially_static_sizes<>, + class _StridesArray=__partially_static_sizes<>, + class=make_index_sequence<_OffsetsArray::__size>, + class=make_index_sequence<_ExtsArray::__size>, + class=make_index_sequence<_StridesArray::__size> +> +struct __assign_op_slice_handler; + +/* clang-format: off */ +template < + class _PreserveLayoutAnalysis, + ptrdiff_t... _Offsets, + ptrdiff_t... _Exts, + ptrdiff_t... _Strides, + size_t... _OffsetIdxs, + size_t... _ExtIdxs, + size_t... _StrideIdxs> +struct __assign_op_slice_handler< + _PreserveLayoutAnalysis, + __partially_static_sizes<_Offsets...>, + __partially_static_sizes<_Exts...>, + __partially_static_sizes<_Strides...>, + integer_sequence, + integer_sequence, + integer_sequence> +{ + // TODO remove this for better compiler performance + static_assert( + _MDSPAN_FOLD_AND((_Strides == dynamic_extent || _Strides > 0) /* && ... */), + " " + ); + static_assert( + _MDSPAN_FOLD_AND((_Offsets == dynamic_extent || _Offsets >= 0) /* && ... */), + " " + ); + + using __offsets_storage_t = __partially_static_sizes<_Offsets...>; + using __extents_storage_t = __partially_static_sizes<_Exts...>; + using __strides_storage_t = __partially_static_sizes<_Strides...>; + __offsets_storage_t __offsets; + __extents_storage_t __exts; + __strides_storage_t __strides; + +#if __INTEL_COMPILER <= 1800 + MDSPAN_INLINE_FUNCTION constexpr __assign_op_slice_handler(__assign_op_slice_handler&& __other) noexcept + : __offsets(::std::move(__other.__offsets)), __exts(::std::move(__other.__exts)), __strides(::std::move(__other.__strides)) + { } + MDSPAN_INLINE_FUNCTION constexpr __assign_op_slice_handler( + __offsets_storage_t&& __o, + __extents_storage_t&& __e, + __strides_storage_t&& __s + ) noexcept + : __offsets(::std::move(__o)), __exts(::std::move(__e)), __strides(::std::move(__s)) + { } #endif -#if !defined(_MDSPAN_USE_RETURN_TYPE_DEDUCTION) || \ - !_MDSPAN_USE_RETURN_TYPE_DEDUCTION - using extents_type = std::experimental::extents; +// Don't define this unless we need it; they have a cost to compile +#ifndef _MDSPAN_USE_RETURN_TYPE_DEDUCTION + using __extents_type = ::std::experimental::extents<_Exts...>; #endif - // TODO defer instantiation of this? - using layout_type = typename conditional< - PreserveLayoutAnalysis::value, - typename PreserveLayoutAnalysis::layout_type_if_preserved, - layout_stride>::type; - - // TODO noexcept specification - template - MDSPAN_INLINE_FUNCTION _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( - (constexpr /* auto */ - _make_layout_mapping_impl(NewLayout) const noexcept), - ( - /* not layout stride, so don't pass dynamic_strides */ - /* return */ typename NewLayout::template mapping< - std::experimental::extents>( - std::experimental::extents( - dynamic_extents - .template __get_n()...)) /* ; */ - )) - - MDSPAN_INLINE_FUNCTION _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( - (constexpr /* auto */ - _make_layout_mapping_impl(layout_stride) - const noexcept), - ( - /* return */ typename layout_stride:: - template mapping>( - std::experimental::extents( - dynamic_extents - .template __get_n()...), - std::array{ - dynamic_strides.template __get_n< - DynamicStrideIdxs>()...}) /* ; */ - )) - - template < - class - OldLayoutMapping> // mostly for deferred instantiation, but maybe we'll use this in the future - MDSPAN_INLINE_FUNCTION _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( - (constexpr /* auto */ - make_layout_mapping(OldLayoutMapping const &) const noexcept), - ( - /* return */ this->_make_layout_mapping_impl( - layout_type{}) /* ; */ - )) - - template - MDSPAN_INLINE_FUNCTION - constexpr auto fwd_extent( - _slice_wrap const &slice) const - noexcept -> decltype(dynamic_extents) { - return dynamic_extents; - } - - template - MDSPAN_INLINE_FUNCTION constexpr auto - fwd_extent(_slice_wrap const &slice) const - noexcept - -> __array_workaround::__array { - return {dynamic_extents.template __get_n()..., - slice.old_extent}; - } - - template - MDSPAN_INLINE_FUNCTION constexpr auto fwd_stride( - _slice_wrap const &slice) const - noexcept -> decltype(dynamic_strides) { - return dynamic_strides; - } - - template - MDSPAN_INLINE_FUNCTION constexpr auto - fwd_stride(_slice_wrap const &slice) const - noexcept - -> __array_workaround::__array { - return {dynamic_strides.template __get_n()..., - slice.old_stride}; - } - // For ptrdiff_t slice, skip the extent and stride, but add an offset corresponding to the value - template + template MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator) - _MDSPAN_CONSTEXPR_14 auto - operator=(_slice_wrap - slice) noexcept - -> _assign_op_slice_handler< - integer_sequence, - integer_sequence, - typename PreserveLayoutAnalysis::encounter_scalar, - __array_workaround::__array, - __array_workaround::__array, - __array_workaround::__array> { - return {__array_workaround::__array( - offsets.template __get_n()..., slice.slice), - dynamic_extents, dynamic_strides}; + _MDSPAN_CONSTEXPR_14 auto + operator=(_slice_wrap<_OldStaticExtent, _OldStaticStride, ptrdiff_t>&& __slice) noexcept + -> __assign_op_slice_handler< + typename _PreserveLayoutAnalysis::encounter_scalar, + __partially_static_sizes<_Offsets..., dynamic_extent>, + __partially_static_sizes<_Exts...>, + __partially_static_sizes<_Strides...>/* intentional space here to work around ICC bug*/> { + return { + __partially_static_sizes<_Offsets..., dynamic_extent>( + __construct_partially_static_array_from_sizes_tag, + __offsets.template __get_n<_OffsetIdxs>()..., __slice.slice), + ::std::move(__exts), + ::std::move(__strides) + }; } // For a std::all, offset 0 and old extent - template + template MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator) - _MDSPAN_CONSTEXPR_14 auto - operator=(_slice_wrap - slice) noexcept - -> _assign_op_slice_handler< - integer_sequence, - integer_sequence, - typename PreserveLayoutAnalysis::encounter_all, - __array_workaround::__array, - decltype(this->fwd_extent(slice)), - decltype(this->fwd_stride(slice))> { - return {__array_workaround::__array( - offsets.template __get_n()..., ptrdiff_t(0)), - this->fwd_extent(slice), this->fwd_stride(slice)}; + _MDSPAN_CONSTEXPR_14 auto + operator=(_slice_wrap<_OldStaticExtent, _OldStaticStride, all_type>&& __slice) noexcept + -> __assign_op_slice_handler< + typename _PreserveLayoutAnalysis::encounter_all, + __partially_static_sizes<_Offsets..., 0>, + __partially_static_sizes<_Exts..., _OldStaticExtent>, + __partially_static_sizes<_Strides..., _OldStaticStride>/* intentional space here to work around ICC bug*/> { + return { + __partially_static_sizes<_Offsets..., 0>( + __construct_partially_static_array_from_sizes_tag, + __offsets.template __get_n<_OffsetIdxs>()..., ptrdiff_t(0)), + __partially_static_sizes<_Exts..., _OldStaticExtent>( + __construct_partially_static_array_from_sizes_tag, + __exts.template __get_n<_ExtIdxs>()..., __slice.old_extent), + __partially_static_sizes<_Strides..., _OldStaticStride>( + __construct_partially_static_array_from_sizes_tag, + __strides.template __get_n<_StrideIdxs>()..., __slice.old_stride) + }; } // For a std::pair, add an offset and add a new dynamic extent (strides still preserved) - template + template MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator) - _MDSPAN_CONSTEXPR_14 auto - operator=(_slice_wrap> - slice) noexcept - -> _assign_op_slice_handler< - integer_sequence, - integer_sequence, - typename PreserveLayoutAnalysis::encounter_pair, - __array_workaround::__array, - __array_workaround::__array, - decltype(this->fwd_stride(slice))> { - return {__array_workaround::__array( - offsets.template __get_n()..., - std::get<0>(slice.slice)), - __array_workaround::__array( - dynamic_extents.template __get_n()..., - std::get<1>(slice.slice) - std::get<0>(slice.slice)), - this->fwd_stride(slice)}; + _MDSPAN_CONSTEXPR_14 auto + operator=(_slice_wrap<_OldStaticExtent, _OldStaticStride, pair>&& __slice) noexcept + -> __assign_op_slice_handler< + typename _PreserveLayoutAnalysis::encounter_pair, + __partially_static_sizes<_Offsets..., dynamic_extent>, + __partially_static_sizes<_Exts..., dynamic_extent>, + __partially_static_sizes<_Strides..., _OldStaticStride>/* intentional space here to work around ICC bug*/> { + return { + __partially_static_sizes<_Offsets..., dynamic_extent>( + __construct_partially_static_array_from_sizes_tag, + __offsets.template __get_n<_OffsetIdxs>()..., ::std::get<0>(__slice.slice)), + __partially_static_sizes<_Exts..., dynamic_extent>( + __construct_partially_static_array_from_sizes_tag, + __exts.template __get_n<_ExtIdxs>()..., ::std::get<1>(__slice.slice) - ::std::get<0>(__slice.slice)), + __partially_static_sizes<_Strides..., _OldStaticStride>( + __construct_partially_static_array_from_sizes_tag, + __strides.template __get_n<_StrideIdxs>()..., __slice.old_stride) + }; } + + // TODO defer instantiation of this? + using layout_type = typename conditional< + _PreserveLayoutAnalysis::value, + typename _PreserveLayoutAnalysis::layout_type_if_preserved, + layout_stride<_Strides...> + >::type; + + // TODO noexcept specification + template + MDSPAN_INLINE_FUNCTION + _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( + ( + _MDSPAN_CONSTEXPR_14 /* auto */ + _make_layout_mapping_impl(NewLayout) noexcept + ), + ( + /* not layout stride, so don't pass dynamic_strides */ + /* return */ typename NewLayout::template mapping<::std::experimental::extents<_Exts...>>( + experimental::extents<_Exts...>::__make_extents_impl(::std::move(__exts)) + ) /* ; */ + ) + ) + + MDSPAN_INLINE_FUNCTION + _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( + ( + _MDSPAN_CONSTEXPR_14 /* auto */ + _make_layout_mapping_impl(layout_stride<_Strides...>) noexcept + ), + ( + /* return */ layout_stride<_Strides...>::template mapping<::std::experimental::extents<_Exts...>> + ::__make_layout_stride_impl(::std::move(__exts), ::std::move(__strides)) /* ; */ + ) + ) + + template // mostly for deferred instantiation, but maybe we'll use this in the future + MDSPAN_INLINE_FUNCTION + _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( + ( + _MDSPAN_CONSTEXPR_14 /* auto */ + make_layout_mapping(OldLayoutMapping const&) noexcept + ), + ( + /* return */ this->_make_layout_mapping_impl(layout_type{}) /* ; */ + ) + ) }; +//============================================================================== + #if _MDSPAN_USE_RETURN_TYPE_DEDUCTION // Forking this because the C++11 version will be *completely* unreadable -template -MDSPAN_INLINE_FUNCTION constexpr auto _subspan_impl( - std::integer_sequence, - basic_mdspan, LP, AP> const &src, - SliceSpecs &&... slices) noexcept { - auto _handled = _MDSPAN_FOLD_ASSIGN_LEFT( - (detail::_assign_op_slice_handler< - integer_sequence, integer_sequence, - typename std::conditional< - std::is_same::value, - detail::preserve_layout_right_analysis<>, - typename std::conditional< - std::is_same::value, - detail::preserve_layout_left_analysis<>, - detail::ignore_layout_preservation>::type>::type>{ - std::array{}, std::array{}, - std::array{}}), - /* = ... = */ +template +MDSPAN_INLINE_FUNCTION +constexpr auto _subspan_impl( + integer_sequence, + basic_mdspan, LP, AP> const& src, + SliceSpecs&&... slices +) noexcept +{ + auto _handled = + _MDSPAN_FOLD_ASSIGN_LEFT( + ( + detail::__assign_op_slice_handler< + detail::preserve_layout_analysis + >{ + __partially_static_sizes<>{}, + __partially_static_sizes<>{}, + __partially_static_sizes<>{} + } + ), + /* = ... = */ detail::_wrap_slice< - Exts, decltype(src.mapping())::template __static_stride_workaround< - Idxs>::value>(slices, - src.extents().template __extent(), - src.mapping().stride(Idxs))); - - ptrdiff_t offset_size = - src.mapping()(_handled.offsets.template __get_n()...); + Exts, decltype(src.mapping())::template __static_stride_workaround::value + >( + slices, src.extents().template __extent(), + src.mapping().template __stride() + ) + ); + + ptrdiff_t offset_size = src.mapping()(_handled.__offsets.template __get_n()...); auto offset_ptr = src.accessor().offset(src.data(), offset_size); auto map = _handled.make_layout_mapping(src.mapping()); auto acc_pol = typename AP::offset_policy(src.accessor()); - return basic_mdspan(std::move(offset_ptr), std::move(map), - std::move(acc_pol)); + return basic_mdspan< + ET, decltype(map.extents()), typename decltype(_handled)::layout_type, decltype(acc_pol) + >( + std::move(offset_ptr), std::move(map), std::move(acc_pol) + ); } #else template -auto _subspan_impl_helper(Src &&src, Handled &&h, - std::integer_sequence) - -> basic_mdspan { - return {src.accessor().offset( - src.data(), src.mapping()(h.offsets.template __get_n()...)), - h.make_layout_mapping(src.mapping()), - typename AP::offset_policy(src.accessor())}; +auto _subspan_impl_helper(Src&& src, Handled&& h, std::integer_sequence) + -> basic_mdspan< + ET, typename Handled::__extents_type, typename Handled::layout_type, typename AP::offset_policy + > +{ + return { + src.accessor().offset(src.data(), src.mapping()(h.__offsets.template __get_n()...)), + h.make_layout_mapping(src.mapping()), + typename AP::offset_policy(src.accessor()) + }; } template @@ -418,19 +431,13 @@ _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( src, _MDSPAN_FOLD_ASSIGN_LEFT( ( - detail::_assign_op_slice_handler< - integer_sequence, - integer_sequence, - typename std::conditional< - std::is_same::value, - detail::preserve_layout_right_analysis<>, - typename std::conditional< - std::is_same::value, - detail::preserve_layout_left_analysis<>, - detail::ignore_layout_preservation - >::type - >::type - >{std::array{}, std::array{}, std::array{}} + detail::__assign_op_slice_handler< + detail::preserve_layout_analysis + >{ + __partially_static_sizes<>{}, + __partially_static_sizes<>{}, + __partially_static_sizes<>{} + } ), /* = ... = */ detail::_wrap_slice< @@ -446,35 +453,46 @@ _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( #endif -template struct _is_layout_stride : std::false_type {}; -template -struct _is_layout_stride> : std::true_type {}; +template struct _is_layout_stride : std::false_type { }; +template struct _is_layout_stride< + layout_stride +> : std::true_type +{ }; } // namespace detail +//============================================================================== + // TODO @proposal-bug sizeof...(SliceSpecs) == sizeof...(Exts) should be a constraint, not a requirement MDSPAN_TEMPLATE_REQUIRES( - class ET, ptrdiff_t... Exts, class LP, class AP, class... SliceSpecs, - /* requires */ - ((_MDSPAN_TRAIT(is_same, LP, layout_left) || - _MDSPAN_TRAIT(is_same, LP, layout_right) || - detail::_is_layout_stride::value) && - _MDSPAN_FOLD_OR((_MDSPAN_TRAIT(is_convertible, SliceSpecs, ptrdiff_t) || - _MDSPAN_TRAIT(is_convertible, SliceSpecs, - pair) || - _MDSPAN_TRAIT(is_convertible, SliceSpecs, - all_type)) /* && ... */) && - sizeof...(SliceSpecs) == sizeof...(Exts))) + class ET, ptrdiff_t... Exts, class LP, class AP, class... SliceSpecs, + /* requires */ ( + ( + _MDSPAN_TRAIT(is_same, LP, layout_left) + || _MDSPAN_TRAIT(is_same, LP, layout_right) + || detail::_is_layout_stride::value + ) && + _MDSPAN_FOLD_AND(( + _MDSPAN_TRAIT(is_convertible, SliceSpecs, ptrdiff_t) + || _MDSPAN_TRAIT(is_convertible, SliceSpecs, pair) + || _MDSPAN_TRAIT(is_convertible, SliceSpecs, all_type) + ) /* && ... */) && + sizeof...(SliceSpecs) == sizeof...(Exts) + ) +) MDSPAN_INLINE_FUNCTION _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE( - (constexpr subspan(basic_mdspan, LP, - AP> const &src, - SliceSpecs... slices) noexcept), - ( - /* return */ - detail::_subspan_impl(std::make_index_sequence{}, - src, slices...) /*;*/ - )) + ( + constexpr subspan( + basic_mdspan, LP, AP> const& src, SliceSpecs... slices + ) noexcept + ), + ( + /* return */ + detail::_subspan_impl(std::make_index_sequence{}, src, slices...) /*;*/ + ) +) +/* clang-format: on */ } // end namespace experimental } // namespace std \ No newline at end of file diff --git a/src/experimental/__p0009_bits/trait_backports.hpp b/src/experimental/__p0009_bits/trait_backports.hpp index 1fef028ad4..4a8ec0fe8e 100644 --- a/src/experimental/__p0009_bits/trait_backports.hpp +++ b/src/experimental/__p0009_bits/trait_backports.hpp @@ -44,8 +44,8 @@ #ifndef MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ #define MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ -#include "config.hpp" #include "macros.hpp" +#include "config.hpp" #include #include // integer_sequence @@ -58,15 +58,16 @@ #if _MDSPAN_USE_VARIABLE_TEMPLATES namespace std { -#define _MDSPAN_BACKPORT_TRAIT(TRAIT) \ - template \ - _MDSPAN_INLINE_VARIABLE constexpr auto TRAIT##_v = TRAIT::value; +#define _MDSPAN_BACKPORT_TRAIT(TRAIT) \ + template _MDSPAN_INLINE_VARIABLE constexpr auto TRAIT##_v = TRAIT::value; _MDSPAN_BACKPORT_TRAIT(is_assignable) _MDSPAN_BACKPORT_TRAIT(is_constructible) _MDSPAN_BACKPORT_TRAIT(is_convertible) _MDSPAN_BACKPORT_TRAIT(is_default_constructible) +_MDSPAN_BACKPORT_TRAIT(is_trivially_destructible) _MDSPAN_BACKPORT_TRAIT(is_same) +_MDSPAN_BACKPORT_TRAIT(is_empty) _MDSPAN_BACKPORT_TRAIT(is_void) #undef _MDSPAN_BACKPORT_TRAIT @@ -87,7 +88,8 @@ _MDSPAN_BACKPORT_TRAIT(is_void) namespace std { -template struct integer_sequence { +template +struct integer_sequence { static constexpr std::size_t size() noexcept { return sizeof...(Vals); } using value_type = T; }; @@ -97,27 +99,28 @@ using index_sequence = std::integer_sequence; namespace __detail { -template struct __make_int_seq_impl; +template +struct __make_int_seq_impl; template -struct __make_int_seq_impl> { +struct __make_int_seq_impl> +{ using type = integer_sequence; }; template -struct __make_int_seq_impl> - : __make_int_seq_impl> {}; +struct __make_int_seq_impl< + T, N, I, integer_sequence +> : __make_int_seq_impl> +{ }; } // end namespace __detail template -using make_integer_sequence = - typename __detail::__make_int_seq_impl>::type; +using make_integer_sequence = typename __detail::__make_int_seq_impl>::type; template -using make_index_sequence = - typename __detail::__make_int_seq_impl>::type; +using make_index_sequence = typename __detail::__make_int_seq_impl>::type; template using index_sequence_for = make_index_sequence; @@ -132,18 +135,17 @@ using index_sequence_for = make_index_sequence; //============================================================================== // {{{1 -#if !defined(_MDSPAN_USE_STANDARD_TRAIT_ALIASES) || \ - !_MDSPAN_USE_STANDARD_TRAIT_ALIASES +#if !defined(_MDSPAN_USE_STANDARD_TRAIT_ALIASES) || !_MDSPAN_USE_STANDARD_TRAIT_ALIASES namespace std { -#define _MDSPAN_BACKPORT_TRAIT_ALIAS(TRAIT) \ +#define _MDSPAN_BACKPORT_TRAIT_ALIAS(TRAIT) \ template using TRAIT##_t = typename TRAIT::type; _MDSPAN_BACKPORT_TRAIT_ALIAS(remove_cv) _MDSPAN_BACKPORT_TRAIT_ALIAS(remove_reference) -template +template using enable_if_t = typename enable_if<_B, _T>::type; #undef _MDSPAN_BACKPORT_TRAIT_ALIAS diff --git a/src/experimental/__p0009_bits/type_list.hpp b/src/experimental/__p0009_bits/type_list.hpp new file mode 100644 index 0000000000..6683a22bf9 --- /dev/null +++ b/src/experimental/__p0009_bits/type_list.hpp @@ -0,0 +1,116 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 2.0 +// Copyright (2019) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Christian R. Trott (crtrott@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "macros.hpp" + +#include "trait_backports.hpp" // make_index_sequence + +namespace std { +namespace experimental { + +//============================================================================== + +namespace detail { + +template struct __type_list { static constexpr auto __size = sizeof...(_Ts); }; + +// Implementation of type_list at() that's heavily optimized for small typelists +template struct __type_at; +template > struct __type_at_large_impl; + +template +struct __type_at_entry { }; + +template +struct __type_at_assign_op_ignore_rest { + template + __type_at_assign_op_ignore_rest<_Result> operator=(_T&&); + using type = _Result; +}; + +struct __type_at_assign_op_impl { + template + __type_at_assign_op_impl operator=(__type_at_entry<_I, _Idx, _T>&&); + template + __type_at_assign_op_ignore_rest<_T> operator=(__type_at_entry<_I, _I, _T>&&); +}; + +template +struct __type_at_large_impl<_I, __type_list<_Ts...>, integer_sequence> + : decltype( + _MDSPAN_FOLD_ASSIGN_LEFT(__type_at_assign_op_impl{}, /* = ... = */ __type_at_entry<_I, _Idxs, _Ts>{}) + ) +{ }; + +template +struct __type_at<_I, __type_list<_Ts...>> + : __type_at_large_impl<_I, __type_list<_Ts...>> +{ }; + +template +struct __type_at<0, __type_list<_T0, _Ts...>> { + using type = _T0; +}; + +template +struct __type_at<1, __type_list<_T0, _T1, _Ts...>> { + using type = _T1; +}; + +template +struct __type_at<2, __type_list<_T0, _T1, _T2, _Ts...>> { + using type = _T2; +}; + +template +struct __type_at<3, __type_list<_T0, _T1, _T2, _T3, _Ts...>> { + using type = _T3; +}; + + +} // namespace detail + +//============================================================================== + +} // end namespace experimental +} // end namespace std \ No newline at end of file diff --git a/src/experimental/mdspan b/src/experimental/mdspan index 0b7e8e129d..9e74d19ae9 100644 --- a/src/experimental/mdspan +++ b/src/experimental/mdspan @@ -56,9 +56,13 @@ #pragma clang diagnostic ignored "-Wreserved-id-macro" #endif +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Werror=undef" +#endif + #include "__p0009_bits/accessor_basic.hpp" #include "__p0009_bits/all_type.hpp" -#include "__p0009_bits/array_workaround.hpp" #include "__p0009_bits/basic_mdspan.hpp" #include "__p0009_bits/dynamic_extent.hpp" #include "__p0009_bits/extents.hpp" @@ -67,9 +71,13 @@ #include "__p0009_bits/layout_right.hpp" #include "__p0009_bits/layout_stride.hpp" #include "__p0009_bits/macros.hpp" -#include "__p0009_bits/mixed_size_storage.hpp" +#include "__p0009_bits/static_array.hpp" #include "__p0009_bits/subspan.hpp" +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + #ifdef __clang__ // Restore clang diagnostics to previous state. #pragma clang diagnostic pop @@ -77,4 +85,4 @@ #ifdef _MSC_FULL_VER #pragma warning(pop) -#endif \ No newline at end of file +#endif