diff --git a/include/xtensor/containers/xfixed.hpp b/include/xtensor/containers/xfixed.hpp index 9661142dc..4ab3a75c3 100644 --- a/include/xtensor/containers/xfixed.hpp +++ b/include/xtensor/containers/xfixed.hpp @@ -325,9 +325,9 @@ namespace xt explicit xfixed_container(const inner_shape_type& shape, layout_type l = L); explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L); - // remove this enable_if when removing the other value_type constructor - template , class EN = std::enable_if_t> - xfixed_container(nested_initializer_list_t t); + template > + xfixed_container(nested_initializer_list_t t) + requires(IX::value != 0); ~xfixed_container() = default; @@ -639,8 +639,9 @@ namespace xt * Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime. */ template - template + template inline xfixed_container::xfixed_container(nested_initializer_list_t t) + requires(IX::value != 0) { XTENSOR_ASSERT_MSG( detail::check_initializer_list_shape::run(t, this->shape()) == true, diff --git a/include/xtensor/containers/xscalar.hpp b/include/xtensor/containers/xscalar.hpp index bfeba09b7..9464f4721 100644 --- a/include/xtensor/containers/xscalar.hpp +++ b/include/xtensor/containers/xscalar.hpp @@ -317,6 +317,9 @@ namespace xt template using is_xscalar = detail::is_xscalar_impl; + template + concept xscalar_concept = is_xscalar>::value; + namespace detail { template diff --git a/include/xtensor/containers/xstorage.hpp b/include/xtensor/containers/xstorage.hpp index a3185259a..28ad238e5 100644 --- a/include/xtensor/containers/xstorage.hpp +++ b/include/xtensor/containers/xstorage.hpp @@ -25,14 +25,6 @@ namespace xt { - - namespace detail - { - template - using require_input_iter = typename std::enable_if< - std::is_convertible::iterator_category, std::input_iterator_tag>::value>::type; - } - template struct is_contiguous_container : std::true_type { @@ -64,7 +56,7 @@ namespace xt explicit uvector(size_type count, const allocator_type& alloc = allocator_type()); uvector(size_type count, const_reference value, const allocator_type& alloc = allocator_type()); - template > + template uvector(InputIt first, InputIt last, const allocator_type& alloc = allocator_type()); uvector(std::initializer_list init, const allocator_type& alloc = allocator_type()); @@ -277,7 +269,7 @@ namespace xt } template - template + template inline uvector::uvector(InputIt first, InputIt last, const allocator_type& alloc) : m_allocator(alloc) , p_begin(nullptr) @@ -675,19 +667,21 @@ namespace xt svector(const std::vector& vec); - template > + template svector(IT begin, IT end, const allocator_type& alloc = allocator_type()); - template > - explicit svector(const svector& rhs); + template + explicit svector(const svector& rhs) + requires(N != N2); svector& operator=(const svector& rhs); svector& operator=(svector&& rhs) noexcept(std::is_nothrow_move_assignable::value); svector& operator=(const std::vector& rhs); svector& operator=(std::initializer_list il); - template > - svector& operator=(const svector& rhs); + template + svector& operator=(const svector& rhs) + requires(N != N2); svector(const svector& other); svector(svector&& other) noexcept(std::is_nothrow_move_constructible::value); @@ -809,7 +803,7 @@ namespace xt } template - template + template inline svector::svector(IT begin, IT end, const allocator_type& alloc) : m_allocator(alloc) { @@ -817,8 +811,9 @@ namespace xt } template - template + template inline svector::svector(const svector& rhs) + requires(N != N2) : m_allocator(rhs.get_allocator()) { assign(rhs.begin(), rhs.end()); @@ -876,8 +871,9 @@ namespace xt } template - template + template inline svector& svector::operator=(const svector& rhs) + requires(N != N2) { m_allocator = std::allocator_traits::select_on_container_copy_construction( rhs.get_allocator() diff --git a/include/xtensor/core/xexpression.hpp b/include/xtensor/core/xexpression.hpp index f32879035..1f8c98194 100644 --- a/include/xtensor/core/xexpression.hpp +++ b/include/xtensor/core/xexpression.hpp @@ -179,6 +179,9 @@ namespace xt template using is_xexpression = is_crtp_base_of; + template + concept xexpression_concept = is_xexpression::value; + template using enable_xexpression = typename std::enable_if::value, R>::type; diff --git a/include/xtensor/core/xshape.hpp b/include/xtensor/core/xshape.hpp index b4027d9dd..28fbe43cc 100644 --- a/include/xtensor/core/xshape.hpp +++ b/include/xtensor/core/xshape.hpp @@ -508,6 +508,9 @@ namespace xt }; } + template + concept fixed_shape_container_concept = detail::is_fixed::shape_type>::value; + template struct promote_shape { diff --git a/include/xtensor/generators/xbuilder.hpp b/include/xtensor/generators/xbuilder.hpp index cb94cea0f..8a2f61147 100644 --- a/include/xtensor/generators/xbuilder.hpp +++ b/include/xtensor/generators/xbuilder.hpp @@ -833,7 +833,7 @@ namespace xt return detail::make_xgenerator(detail::concatenate_impl(std::move(t), axis), shape); } - template ::value>> + template inline auto concatenate(std::tuple&& t) { using shape_type = detail::concat_fixed_shape_t::shape_type...>; diff --git a/include/xtensor/generators/xgenerator.hpp b/include/xtensor/generators/xgenerator.hpp index 95c4fb753..f4dfc191f 100644 --- a/include/xtensor/generators/xgenerator.hpp +++ b/include/xtensor/generators/xgenerator.hpp @@ -60,6 +60,9 @@ namespace xt template class xgenerator; + template + concept xgenerator_concept = is_specialization_of>::value; + template struct xiterable_inner_types> { @@ -80,10 +83,9 @@ namespace xt * overlapping_memory_checker_traits * *************************************/ - template - struct overlapping_memory_checker_traits< - E, - std::enable_if_t::value && is_specialization_of::value>> + template + requires(without_memory_address_concept) + struct overlapping_memory_checker_traits { static bool check_overlap(const E&, const memory_range&) { @@ -165,8 +167,9 @@ namespace xt template const_stepper stepper_end(const O& shape, layout_type) const noexcept; - template ::value>> - void assign_to(xexpression& e) const noexcept; + template + void assign_to(xexpression& e) const noexcept + requires(has_assign_to_v); const functor_type& functor() const noexcept; @@ -371,8 +374,9 @@ namespace xt } template - template + template inline void xgenerator::assign_to(xexpression& e) const noexcept + requires(has_assign_to_v) { e.derived_cast().resize(m_shape); m_f.assign_to(e); diff --git a/include/xtensor/generators/xrandom.hpp b/include/xtensor/generators/xrandom.hpp index dbb2819d7..5e365f667 100644 --- a/include/xtensor/generators/xrandom.hpp +++ b/include/xtensor/generators/xrandom.hpp @@ -27,6 +27,7 @@ #include "../core/xtensor_config.hpp" #include "../generators/xbuilder.hpp" #include "../generators/xgenerator.hpp" +#include "../misc/xtl_concepts.hpp" #include "../views/xindex_view.hpp" #include "../views/xview.hpp" @@ -175,13 +176,11 @@ namespace xt template void shuffle(xexpression& e, E& engine = random::get_default_random_engine()); - template - std::enable_if_t::value, xtensor> - permutation(T e, E& engine = random::get_default_random_engine()); + template + xtensor permutation(T e, E& engine = random::get_default_random_engine()); - template - std::enable_if_t>::value, std::decay_t> - permutation(T&& e, E& engine = random::get_default_random_engine()); + template + std::decay_t permutation(T&& e, E& engine = random::get_default_random_engine()); template xtensor choice( @@ -835,8 +834,8 @@ namespace xt * * @return randomly permuted copy of container or arange. */ - template - std::enable_if_t::value, xtensor> permutation(T e, E& engine) + template + xtensor permutation(T e, E& engine) { xt::xtensor res = xt::arange(e); shuffle(res, engine); @@ -844,8 +843,8 @@ namespace xt } /// @cond DOXYGEN_INCLUDE_SFINAE - template - std::enable_if_t>::value, std::decay_t> permutation(T&& e, E& engine) + template + std::decay_t permutation(T&& e, E& engine) { using copy_type = std::decay_t; copy_type res = e; diff --git a/include/xtensor/misc/xfft.hpp b/include/xtensor/misc/xfft.hpp index 5e54303ee..954b55a9b 100644 --- a/include/xtensor/misc/xfft.hpp +++ b/include/xtensor/misc/xfft.hpp @@ -12,6 +12,7 @@ #include "../misc/xcomplex.hpp" #include "../views/xaxis_slice_iterator.hpp" #include "../views/xview.hpp" +#include "./xtl_concepts.hpp" namespace xt { @@ -19,9 +20,7 @@ namespace xt { namespace detail { - template < - class E, - typename std::enable_if::type::value_type>::value, bool>::type = true> + template inline auto radix2(E&& e) { using namespace xt::placeholders; @@ -125,72 +124,59 @@ namespace xt * @param axis the axis along which to perform the 1D FFT * @return a transformed xarray of the specified precision */ - template < - class E, - typename std::enable_if::type::value_type>::value, bool>::type = true> + template inline auto fft(E&& e, std::ptrdiff_t axis = -1) { - using value_type = typename std::decay_t::value_type; - using precision = typename value_type::value_type; - const auto saxis = xt::normalize_axis(e.dimension(), axis); - const size_t N = e.shape(saxis); - const bool powerOfTwo = !(N == 0) && !(N & (N - 1)); - xt::xarray> out = xt::eval(e); - auto begin = xt::axis_slice_begin(out, saxis); - auto end = xt::axis_slice_end(out, saxis); - for (auto iter = begin; iter != end; iter++) + using value_type = typename std::decay::type::value_type; + if constexpr (xtl::is_complex::type::value_type>::value) { - if (powerOfTwo) - { - xt::noalias(*iter) = detail::radix2(*iter); - } - else + using precision = typename value_type::value_type; + const auto saxis = xt::normalize_axis(e.dimension(), axis); + const size_t N = e.shape(saxis); + const bool powerOfTwo = !(N == 0) && !(N & (N - 1)); + xt::xarray> out = xt::eval(e); + auto begin = xt::axis_slice_begin(out, saxis); + auto end = xt::axis_slice_end(out, saxis); + for (auto iter = begin; iter != end; iter++) { - xt::noalias(*iter) = detail::transform_bluestein(*iter); + if (powerOfTwo) + { + xt::noalias(*iter) = detail::radix2(*iter); + } + else + { + xt::noalias(*iter) = detail::transform_bluestein(*iter); + } } + return out; } - return out; - } - - /** - * @brief 1D FFT of an Nd array along a specified axis - * @param e an Nd expression to be transformed to the fourier domain - * @param axis the axis along which to perform the 1D FFT - * @return a transformed xarray of the specified precision - */ - template < - class E, - typename std::enable_if::type::value_type>::value, bool>::type = true> - inline auto fft(E&& e, std::ptrdiff_t axis = -1) - { - using value_type = typename std::decay::type::value_type; - return fft(xt::cast>(e), axis); - } - - template < - class E, - typename std::enable_if::type::value_type>::value, bool>::type = true> - auto ifft(E&& e, std::ptrdiff_t axis = -1) - { - // check the length of the data on that axis - const std::size_t n = e.shape(axis); - if (n == 0) + else { - XTENSOR_THROW(std::runtime_error, "Cannot take the iFFT along an empty dimention"); + return fft(xt::cast>(e), axis); } - auto complex_args = xt::conj(e); - auto fft_res = xt::fft::fft(complex_args, axis); - fft_res = xt::conj(fft_res); - return fft_res; } - template < - class E, - typename std::enable_if::type::value_type>::value, bool>::type = true> + template inline auto ifft(E&& e, std::ptrdiff_t axis = -1) { - using value_type = typename std::decay::type::value_type; - return ifft(xt::cast>(e), axis); + if constexpr (xtl::is_complex::type::value_type>::value) + { + // check the length of the data on that axis + const std::size_t n = e.shape(axis); + if (n == 0) + { + XTENSOR_THROW(std::runtime_error, "Cannot take the iFFT along an empty dimention"); + } + auto complex_args = xt::conj(e); + auto fft_res = xt::fft::fft(complex_args, axis); + fft_res = xt::conj(fft_res); + return fft_res; + } + else + { + using value_type = typename std::decay::type::value_type; + return ifft(xt::cast>(e), axis); + } } /* diff --git a/include/xtensor/misc/xmanipulation.hpp b/include/xtensor/misc/xmanipulation.hpp index 42395dd57..f0af92892 100644 --- a/include/xtensor/misc/xmanipulation.hpp +++ b/include/xtensor/misc/xmanipulation.hpp @@ -22,6 +22,7 @@ #include "../utils/xutils.hpp" #include "../views/xrepeat.hpp" #include "../views/xstrided_view.hpp" +#include "xtl_concepts.hpp" namespace xt { @@ -64,7 +65,7 @@ namespace xt template auto squeeze(E&& e); - template ::value, int> = 0> + template auto squeeze(E&& e, S&& axis, Tag check_policy = Tag()); template @@ -210,20 +211,21 @@ namespace xt return transpose_impl(std::forward(e), std::forward(permutation), check_policy::none()); } - template >::value>* = nullptr> - inline void compute_transposed_strides(E&& e, const S&, X& strides) + template + inline void compute_transposed_strides(E&& e, const S& shape, X& strides) { - std::copy(e.strides().crbegin(), e.strides().crend(), strides.begin()); - } - - template >::value>* = nullptr> - inline void compute_transposed_strides(E&&, const S& shape, X& strides) - { - // In the case where E does not have a data interface, the transposition - // makes use of a flat storage adaptor that has layout XTENSOR_DEFAULT_TRAVERSAL - // which should be the one inverted. - layout_type l = transpose_layout(XTENSOR_DEFAULT_TRAVERSAL); - compute_strides(shape, l, strides); + if constexpr (has_data_interface>::value) + { + std::copy(e.strides().crbegin(), e.strides().crend(), strides.begin()); + } + else + { + // In the case where E does not have a data interface, the transposition + // makes use of a flat storage adaptor that has layout XTENSOR_DEFAULT_TRAVERSAL + // which should be the one inverted. + layout_type l = transpose_layout(XTENSOR_DEFAULT_TRAVERSAL); + compute_strides(shape, l, strides); + } } } @@ -588,7 +590,7 @@ namespace xt * @param check_policy select check_policy. With check_policy::full(), selecting an axis * which is greater than one will throw a runtime_error. */ - template ::value, int>> + template inline auto squeeze(E&& e, S&& axis, Tag check_policy) { return detail::squeeze_impl(std::forward(e), std::forward(axis), check_policy); diff --git a/include/xtensor/misc/xset_operation.hpp b/include/xtensor/misc/xset_operation.hpp index 598382855..94b7e23a7 100644 --- a/include/xtensor/misc/xset_operation.hpp +++ b/include/xtensor/misc/xset_operation.hpp @@ -87,8 +87,9 @@ namespace xt * @param test_elements an array * @return a boolean array */ - template ::value>> + template inline auto isin(E&& element, F&& test_elements) noexcept + requires(has_iterator_interface_concept) { auto lambda = detail::lambda_isin::value>::make(std::forward(test_elements )); @@ -106,7 +107,7 @@ namespace xt * @param test_elements_end iterator to the end of an array * @return a boolean array */ - template ::value>> + template inline auto isin(E&& element, I&& test_elements_begin, I&& test_elements_end) noexcept { auto lambda = [&test_elements_begin, &test_elements_end](const auto& t) @@ -143,8 +144,9 @@ namespace xt * @param test_elements an array * @return a boolean array */ - template ::value>> + template inline auto in1d(E&& element, F&& test_elements) noexcept + requires(has_iterator_interface_concept) { XTENSOR_ASSERT(element.dimension() == 1ul); XTENSOR_ASSERT(test_elements.dimension() == 1ul); @@ -162,7 +164,7 @@ namespace xt * @param test_elements_end iterator to the end of an array * @return a boolean array */ - template ::value>> + template inline auto in1d(E&& element, I&& test_elements_begin, I&& test_elements_end) noexcept { XTENSOR_ASSERT(element.dimension() == 1ul); diff --git a/include/xtensor/misc/xsort.hpp b/include/xtensor/misc/xsort.hpp index 9261ac8c4..aa9ea4cfa 100644 --- a/include/xtensor/misc/xsort.hpp +++ b/include/xtensor/misc/xsort.hpp @@ -561,11 +561,7 @@ namespace xt * * @return partially sorted xcontainer */ - template < - class E, - class C, - class R = detail::flatten_sort_result_type_t, - class = std::enable_if_t::value, int>> + template > inline R partition(const xexpression& e, C kth_container, placeholders::xtuph /*ax*/) { const auto& de = e.derived_cast(); @@ -596,7 +592,7 @@ namespace xt return partition(e, std::array({kth}), tag); } - template ::value, int>> + template inline auto partition(const xexpression& e, C kth_container, std::ptrdiff_t axis = -1) { using eval_type = typename detail::sort_eval_type::type; @@ -658,9 +654,8 @@ namespace xt */ template < class E, - class C, - class R = typename detail::linear_argsort_result_type::type>::type, - class = std::enable_if_t::value, int>> + xtl::non_integral_concept C, + class R = typename detail::linear_argsort_result_type::type>::type> inline R argpartition(const xexpression& e, C kth_container, placeholders::xtuph) { using eval_type = typename detail::sort_eval_type::type; @@ -704,7 +699,7 @@ namespace xt return argpartition(e, std::array({kth}), tag); } - template ::value, int>> + template inline auto argpartition(const xexpression& e, C kth_container, std::ptrdiff_t axis = -1) { using eval_type = typename detail::sort_eval_type::type; diff --git a/include/xtensor/misc/xtl_concepts.hpp b/include/xtensor/misc/xtl_concepts.hpp new file mode 100644 index 000000000..163139812 --- /dev/null +++ b/include/xtensor/misc/xtl_concepts.hpp @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ + +#ifndef XTENSOR_CONCEPTS_HPP +#define XTENSOR_CONCEPTS_HPP + +#include +#include + +namespace xtl +{ + template + concept integral_concept = xtl::is_integral::value; + template + concept non_integral_concept = !xtl::is_integral::value; + template + concept complex_concept = xtl::is_complex::type::value_type>::value; +} + +#endif // XTENSOR_CONCEPTS_HPP diff --git a/include/xtensor/utils/xtensor_simd.hpp b/include/xtensor/utils/xtensor_simd.hpp index b6cad1470..59816114b 100644 --- a/include/xtensor/utils/xtensor_simd.hpp +++ b/include/xtensor/utils/xtensor_simd.hpp @@ -269,6 +269,9 @@ namespace xt { }; + template + concept has_simd_interface_concept = has_simd_interface::value; + template struct has_simd_type : std::integral_constant>::value> { diff --git a/include/xtensor/utils/xutils.hpp b/include/xtensor/utils/xutils.hpp index 91d402e7f..8f40b0c05 100644 --- a/include/xtensor/utils/xutils.hpp +++ b/include/xtensor/utils/xutils.hpp @@ -586,6 +586,9 @@ namespace xt { }; + template + concept has_data_interface_concept = has_data_interface::value; + template struct has_strides : std::false_type { @@ -606,6 +609,9 @@ namespace xt { }; + template + concept has_iterator_interface_concept = has_iterator_interface::value; + /****************************** * is_iterator implementation * ******************************/ @@ -624,6 +630,9 @@ namespace xt { }; + template + concept iterator_concept = is_iterator::value; + /******************************************** * xtrivial_default_construct implemenation * ********************************************/ @@ -793,6 +802,9 @@ namespace xt { }; + template + constexpr bool has_assign_to_v = has_assign_to::value; + /************************************* * overlapping_memory_checker_traits * *************************************/ @@ -807,6 +819,11 @@ namespace xt { }; + template + concept with_memory_address_concept = has_memory_address>::value; + template + concept without_memory_address_concept = !has_memory_address>::value; + struct memory_range { // Checking pointer overlap is more correct in integer values, diff --git a/include/xtensor/views/xview.hpp b/include/xtensor/views/xview.hpp index 85515da22..be4c05e1a 100644 --- a/include/xtensor/views/xview.hpp +++ b/include/xtensor/views/xview.hpp @@ -289,6 +289,11 @@ namespace xt }; } + template + concept contiguous_view_concept = detail::is_contiguous_view::value; + template + concept strided_view_concept = detail::is_strided_view, S...>::value; + template struct xcontainer_inner_types> { @@ -493,95 +498,91 @@ namespace xt template bool has_linear_assign(const ST& strides) const; - template - std::enable_if_t stepper_begin(const ST& shape); - template - std::enable_if_t stepper_end(const ST& shape, layout_type l); - - template - std::enable_if_t stepper_begin(const ST& shape) const; - template - std::enable_if_t stepper_end(const ST& shape, layout_type l) const; - - template - std::enable_if_t stepper_begin(const ST& shape); - template - std::enable_if_t stepper_end(const ST& shape, layout_type l); + template + stepper stepper_begin(const ST& shape); + template + stepper stepper_end(const ST& shape, layout_type l); - template - std::enable_if_t stepper_begin(const ST& shape) const; - template - std::enable_if_t stepper_end(const ST& shape, layout_type l) const; + template + const_stepper stepper_begin(const ST& shape) const; + template + const_stepper stepper_end(const ST& shape, layout_type l) const; template - std::enable_if_t::value, storage_type&> storage(); + storage_type& storage() + requires(has_data_interface_concept); template - std::enable_if_t::value, const storage_type&> storage() const; + const storage_type& storage() const + requires(has_data_interface_concept); template - std::enable_if_t::value && is_strided_view, linear_iterator> linear_begin(); + linear_iterator linear_begin() + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, linear_iterator> linear_end(); + linear_iterator linear_end() + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_linear_iterator> - linear_begin() const; + const_linear_iterator linear_begin() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_linear_iterator> - linear_end() const; + const_linear_iterator linear_end() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_linear_iterator> - linear_cbegin() const; + const_linear_iterator linear_cbegin() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_linear_iterator> - linear_cend() const; + const_linear_iterator linear_cend() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, reverse_linear_iterator> - linear_rbegin(); + reverse_linear_iterator linear_rbegin() + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, reverse_linear_iterator> - linear_rend(); + reverse_linear_iterator linear_rend() + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> - linear_rbegin() const; + const_reverse_linear_iterator linear_rbegin() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> - linear_rend() const; + const_reverse_linear_iterator linear_rend() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> - linear_crbegin() const; + const_reverse_linear_iterator linear_crbegin() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> - linear_crend() const; + const_reverse_linear_iterator linear_crend() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const inner_strides_type&> - strides() const; + const inner_strides_type& strides() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const inner_strides_type&> - backstrides() const; + const inner_strides_type& backstrides() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, const_pointer> data() const; + const_pointer data() const + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, pointer> data(); + pointer data() + requires(has_data_interface_concept and strided_view_concept); template - std::enable_if_t::value && is_strided_view, std::size_t> - data_offset() const noexcept; + std::size_t data_offset() const noexcept + requires(has_data_interface_concept and strided_view_concept); template inline It data_xbegin_impl(It begin) const noexcept; @@ -595,13 +596,13 @@ namespace xt inline const_container_iterator data_xend(layout_type l, size_type offset) const noexcept; // Conversion operator enabled for statically "scalar" views - template >::value, int>> + template operator reference() { return (*this)(); } - template >::value, int>> + template operator const_reference() const { return (*this)(); @@ -613,11 +614,9 @@ namespace xt xtl::xclosure_pointer operator&() const&; xtl::xclosure_pointer operator&() &&; - template < - class E, - class T = xexpression_type, - class = std::enable_if_t::value && is_contiguous_view, int>> - void assign_to(xexpression& e, bool force_resize) const; + template + void assign_to(xexpression& e, bool force_resize) const + requires(has_data_interface_concept and contiguous_view_concept); template using rebind_t = xview; @@ -632,30 +631,33 @@ namespace xt template using simd_return_type = xt_simd::simd_return_type; - template - using enable_simd_interface = std::enable_if_t::value && is_strided_view, R>; - template - enable_simd_interface store_simd(size_type i, const simd& e); + void store_simd(size_type i, const simd& e) + requires(has_simd_interface_concept and strided_view_concept); template < class align, class requested_type = value_type, std::size_t N = xt_simd::simd_traits::size, class T = xexpression_type> - enable_simd_interface> load_simd(size_type i) const; + simd_return_type load_simd(size_type i) const + requires(has_simd_interface_concept and strided_view_concept); template - enable_simd_interface data_element(size_type i); + reference data_element(size_type i) + requires(has_simd_interface_concept and strided_view_concept); template - enable_simd_interface data_element(size_type i) const; + const_reference data_element(size_type i) const + requires(has_simd_interface_concept and strided_view_concept); template - enable_simd_interface flat(size_type i); + reference flat(size_type i) + requires(has_simd_interface_concept and strided_view_concept); template - enable_simd_interface flat(size_type i) const; + const_reference flat(size_type i) const + requires(has_simd_interface_concept and strided_view_concept); private: @@ -709,10 +711,7 @@ namespace xt const_reference access_impl(std::index_sequence, Args... args) const; template ::size_type I, class... Args> - std::enable_if_t::value, size_type> index(Args... args) const; - - template ::size_type I, class... Args> - std::enable_if_t::value, size_type> index(Args... args) const; + size_type index(Args... args) const; template ::size_type, class T> size_type sliced_access(const xslice& slice) const; @@ -1152,111 +1151,112 @@ namespace xt */ template template - inline auto xview::storage() -> std::enable_if_t::value, storage_type&> + inline auto xview::storage() -> storage_type& + requires(has_data_interface_concept) { return m_e.storage(); } template template - inline auto xview::storage() const - -> std::enable_if_t::value, const storage_type&> + inline auto xview::storage() const -> const storage_type& + requires(has_data_interface_concept) { return m_e.storage(); } template template - auto xview::linear_begin() - -> std::enable_if_t::value && is_strided_view, linear_iterator> + auto xview::linear_begin() -> linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return m_e.storage().begin() + data_offset(); } template template - auto xview::linear_end() - -> std::enable_if_t::value && is_strided_view, linear_iterator> + auto xview::linear_end() -> linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return m_e.storage().begin() + data_offset() + this->size(); } template template - auto xview::linear_begin() const - -> std::enable_if_t::value && is_strided_view, const_linear_iterator> + auto xview::linear_begin() const -> const_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return linear_cbegin(); } template template - auto xview::linear_end() const - -> std::enable_if_t::value && is_strided_view, const_linear_iterator> + auto xview::linear_end() const -> const_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return linear_cend(); } template template - auto xview::linear_cbegin() const - -> std::enable_if_t::value && is_strided_view, const_linear_iterator> + auto xview::linear_cbegin() const -> const_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return m_e.storage().cbegin() + data_offset(); } template template - auto xview::linear_cend() const - -> std::enable_if_t::value && is_strided_view, const_linear_iterator> + auto xview::linear_cend() const -> const_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return m_e.storage().cbegin() + data_offset() + this->size(); } template template - auto xview::linear_rbegin() - -> std::enable_if_t::value && is_strided_view, reverse_linear_iterator> + auto xview::linear_rbegin() -> reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return reverse_linear_iterator(linear_end()); } template template - auto xview::linear_rend() - -> std::enable_if_t::value && is_strided_view, reverse_linear_iterator> + auto xview::linear_rend() -> reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return reverse_linear_iterator(linear_begin()); } template template - auto xview::linear_rbegin() const - -> std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> + auto xview::linear_rbegin() const -> const_reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return linear_crbegin(); } template template - auto xview::linear_rend() const - -> std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> + auto xview::linear_rend() const -> const_reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return linear_crend(); } template template - auto xview::linear_crbegin() const - -> std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> + auto xview::linear_crbegin() const -> const_reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return const_reverse_linear_iterator(linear_end()); } template template - auto xview::linear_crend() const - -> std::enable_if_t::value && is_strided_view, const_reverse_linear_iterator> + auto xview::linear_crend() const -> const_reverse_linear_iterator + requires(has_data_interface_concept and strided_view_concept) { return const_reverse_linear_iterator(linear_begin()); } @@ -1267,44 +1267,42 @@ namespace xt template template inline auto xview::strides() const - -> std::enable_if_t::value && is_strided_view, const inner_strides_type&> - { - if (!m_strides_computed) - { - compute_strides(std::integral_constant{}); - m_strides_computed = true; + -> const inner_strides_type& requires(has_data_interface_conceptand strided_view_concept) { + if (!m_strides_computed) + { + compute_strides(std::integral_constant{}); + m_strides_computed = true; + } + return m_strides; } - return m_strides; - } template template inline auto xview::backstrides() const - -> std::enable_if_t::value && is_strided_view, const inner_strides_type&> - { - if (!m_strides_computed) - { - compute_strides(std::integral_constant{}); - m_strides_computed = true; + -> const inner_strides_type& requires(has_data_interface_conceptand strided_view_concept) { + if (!m_strides_computed) + { + compute_strides(std::integral_constant{}); + m_strides_computed = true; + } + return m_backstrides; } - return m_backstrides; - } /** * Return the pointer to the underlying buffer. */ template template - inline auto xview::data() const - -> std::enable_if_t::value && is_strided_view, const_pointer> + inline auto xview::data() const -> const_pointer + requires(has_data_interface_concept and strided_view_concept) { return m_e.data(); } template template - inline auto xview::data() - -> std::enable_if_t::value && is_strided_view, pointer> + inline auto xview::data() -> pointer + requires(has_data_interface_concept and strided_view_concept) { return m_e.data(); } @@ -1335,8 +1333,8 @@ namespace xt */ template template - inline auto xview::data_offset() const noexcept - -> std::enable_if_t::value && is_strided_view, std::size_t> + inline std::size_t xview::data_offset() const noexcept + requires(has_data_interface_concept and strided_view_concept) { if (!m_strides_computed) { @@ -1451,8 +1449,9 @@ namespace xt // Assign to operator enabled for contigous views template - template + template void xview::assign_to(xexpression& e, bool force_resize) const + requires(has_data_interface_concept and contiguous_view_concept) { auto& de = e.derived_cast(); de.resize(shape(), force_resize); @@ -1475,36 +1474,40 @@ namespace xt template template - inline auto xview::store_simd(size_type i, const simd& e) -> enable_simd_interface + inline auto xview::store_simd(size_type i, const simd& e) -> void + requires(has_simd_interface_concept and strided_view_concept) { return m_e.template store_simd(data_offset() + i, e); } template template - inline auto xview::load_simd(size_type i) const - -> enable_simd_interface> + inline auto xview::load_simd(size_type i) const -> simd_return_type + requires(has_simd_interface_concept and strided_view_concept) { return m_e.template load_simd(data_offset() + i); } template template - inline auto xview::data_element(size_type i) -> enable_simd_interface + inline auto xview::data_element(size_type i) -> reference + requires(has_simd_interface_concept and strided_view_concept) { return m_e.data_element(data_offset() + i); } template template - inline auto xview::data_element(size_type i) const -> enable_simd_interface + inline auto xview::data_element(size_type i) const -> const_reference + requires(has_simd_interface_concept and strided_view_concept) { return m_e.data_element(data_offset() + i); } template template - inline auto xview::flat(size_type i) -> enable_simd_interface + inline auto xview::flat(size_type i) -> reference + requires(has_simd_interface_concept and strided_view_concept) { XTENSOR_ASSERT(is_contiguous()); return m_e.flat(data_offset() + i); @@ -1512,7 +1515,8 @@ namespace xt template template - inline auto xview::flat(size_type i) const -> enable_simd_interface + inline auto xview::flat(size_type i) const -> const_reference + requires(has_simd_interface_concept and strided_view_concept) { XTENSOR_ASSERT(is_contiguous()); return m_e.flat(data_offset() + i); @@ -1636,21 +1640,19 @@ namespace xt template template ::size_type I, class... Args> - inline auto xview::index(Args... args) const - -> std::enable_if_t::value, size_type> + inline auto xview::index(Args... args) const -> size_type { - return sliced_access(I) + newaxis_count_before(I + 1)>( - std::get(I + 1)>(m_slices), - args... - ); - } - - template - template ::size_type I, class... Args> - inline auto xview::index(Args... args) const - -> std::enable_if_t::value, size_type> - { - return argument() + newaxis_count()>(args...); + if constexpr (lesser_condition::value) + { + return sliced_access(I) + newaxis_count_before(I + 1)>( + std::get(I + 1)>(m_slices), + args... + ); + } + else + { + return argument() + newaxis_count()>(args...); + } } template @@ -1929,75 +1931,65 @@ namespace xt ***************/ template - template - inline auto xview::stepper_begin(const ST& shape) -> std::enable_if_t - { - size_type offset = shape.size() - this->dimension(); - return stepper(this, m_e.stepper_begin(m_e.shape()), offset); - } - - template - template - inline auto xview::stepper_end(const ST& shape, layout_type l) - -> std::enable_if_t - { - size_type offset = shape.size() - this->dimension(); - return stepper(this, m_e.stepper_end(m_e.shape(), l), offset, true, l); - } - - template - template - inline auto xview::stepper_begin(const ST& shape) const - -> std::enable_if_t - { - size_type offset = shape.size() - this->dimension(); - const xexpression_type& e = m_e; - return const_stepper(this, e.stepper_begin(m_e.shape()), offset); - } - - template - template - inline auto xview::stepper_end(const ST& shape, layout_type l) const - -> std::enable_if_t - { - size_type offset = shape.size() - this->dimension(); - const xexpression_type& e = m_e; - return const_stepper(this, e.stepper_end(m_e.shape(), l), offset, true, l); - } - - template - template - inline auto xview::stepper_begin(const ST& shape) -> std::enable_if_t + template + inline auto xview::stepper_begin(const ST& shape) -> stepper { - size_type offset = shape.size() - this->dimension(); - return stepper(this, data_xbegin(), offset); + const size_type offset = shape.size() - this->dimension(); + if constexpr (is_strided_view) + { + return stepper(this, data_xbegin(), offset); + } + else + { + return stepper(this, m_e.stepper_begin(m_e.shape()), offset); + } } template - template - inline auto xview::stepper_end(const ST& shape, layout_type l) - -> std::enable_if_t + template + inline auto xview::stepper_end(const ST& shape, layout_type l) -> stepper { - size_type offset = shape.size() - this->dimension(); - return stepper(this, data_xend(l, offset), offset); + const size_type offset = shape.size() - this->dimension(); + if constexpr (is_strided_view) + { + return stepper(this, data_xend(l, offset), offset); + } + else + { + return stepper(this, m_e.stepper_end(m_e.shape(), l), offset, true, l); + } } template - template - inline auto xview::stepper_begin(const ST& shape) const - -> std::enable_if_t + template + inline auto xview::stepper_begin(const ST& shape) const -> const_stepper { - size_type offset = shape.size() - this->dimension(); - return const_stepper(this, data_xbegin(), offset); + const size_type offset = shape.size() - this->dimension(); + if constexpr (is_strided_view) + { + return const_stepper(this, data_xbegin(), offset); + } + else + { + const xexpression_type& e = m_e; + return const_stepper(this, e.stepper_begin(m_e.shape()), offset); + } } template - template - inline auto xview::stepper_end(const ST& shape, layout_type l) const - -> std::enable_if_t + template + inline auto xview::stepper_end(const ST& shape, layout_type l) const -> const_stepper { - size_type offset = shape.size() - this->dimension(); - return const_stepper(this, data_xend(l, offset), offset); + const size_type offset = shape.size() - this->dimension(); + if constexpr (is_strided_view) + { + return const_stepper(this, data_xend(l, offset), offset); + } + else + { + const xexpression_type& e = m_e; + return const_stepper(this, e.stepper_end(m_e.shape(), l), offset, true, l); + } } /********************************