diff --git a/include/xtensor/views/xdynamic_view.hpp b/include/xtensor/views/xdynamic_view.hpp index 5ab298f23..b270392b8 100644 --- a/include/xtensor/views/xdynamic_view.hpp +++ b/include/xtensor/views/xdynamic_view.hpp @@ -324,7 +324,7 @@ namespace xt namespace detail { template - class xfake_slice : public xslice> + class xfake_slice { public: diff --git a/include/xtensor/views/xslice.hpp b/include/xtensor/views/xslice.hpp index a7a4dae6e..4ea322152 100644 --- a/include/xtensor/views/xslice.hpp +++ b/include/xtensor/views/xslice.hpp @@ -10,6 +10,7 @@ #ifndef XTENSOR_SLICE_HPP #define XTENSOR_SLICE_HPP +#include #include #include #include @@ -19,6 +20,7 @@ #include "../containers/xstorage.hpp" #include "../core/xtensor_config.hpp" +#include "../misc/xtl_concepts.hpp" #include "../utils/xutils.hpp" #ifndef XTENSOR_CONSTEXPR @@ -35,36 +37,94 @@ namespace xt { /********************** - * xslice declaration * + * xslice type traits * **********************/ - template - class xslice - { - public: + // Forward declarations + template + class xrange; + + template + class xstepped_range; - using derived_type = D; + template + class xall; + + template + class xnewaxis; - derived_type& derived_cast() noexcept; - const derived_type& derived_cast() const noexcept; + template + class xkeep_slice; - protected: + template + class xdrop_slice; - xslice() = default; - ~xslice() = default; + namespace detail + { + template class SliceType> + struct is_specific_slice_impl : std::false_type + { + }; - xslice(const xslice&) = default; - xslice& operator=(const xslice&) = default; + template class SliceType> + struct is_specific_slice_impl, SliceType> : std::true_type + { + }; - xslice(xslice&&) = default; - xslice& operator=(xslice&&) = default; + template + struct is_xslice_impl : std::disjunction< + is_specific_slice_impl, + is_specific_slice_impl, + is_specific_slice_impl, + is_specific_slice_impl, + is_specific_slice_impl, + is_specific_slice_impl> + { + }; + } + + template + struct is_xslice : detail::is_xslice_impl + { }; template - using is_xslice = std::is_base_of, S>; + concept xslice_concept = is_xslice::value; + + template + concept xrange_concept = detail::is_specific_slice_impl, xrange>::value; + + template + concept xstepped_range_concept = detail::is_specific_slice_impl, xstepped_range>::value; + + template + concept xall_concept = detail::is_specific_slice_impl, xall>::value; + + template + concept xnewaxis_concept = detail::is_specific_slice_impl, xnewaxis>::value; + + template + concept xkeep_slice_concept = detail::is_specific_slice_impl, xkeep_slice>::value; + + template + concept xdrop_slice_concept = detail::is_specific_slice_impl, xdrop_slice>::value; + + template + concept nonstrided_slice_concept = xkeep_slice_concept || xdrop_slice_concept; + + template + concept strided_slice_concept = xslice_concept && !nonstrided_slice_concept; + + template + concept slice_or_scalar_concept = xslice_concept || xtl::integral_concept; + + template + concept strided_compatible_concept = slice_or_scalar_concept && !nonstrided_slice_concept; template - using has_xslice = std::disjunction...>; + struct has_xslice : std::bool_constant<(xslice_concept || ...)> + { + }; /************** * slice tags * @@ -99,7 +159,7 @@ namespace xt **********************/ template - class xrange : public xslice> + class xrange { public: @@ -143,7 +203,7 @@ namespace xt ******************************/ template - class xstepped_range : public xslice> + class xstepped_range { public: @@ -188,7 +248,7 @@ namespace xt ********************/ template - class xall : public xslice> + class xall { public: @@ -259,7 +319,7 @@ namespace xt ************************/ template - class xnewaxis : public xslice> + class xnewaxis { public: @@ -306,21 +366,8 @@ namespace xt template class xkeep_slice; - namespace detail - { - template - struct is_xkeep_slice : std::false_type - { - }; - - template - struct is_xkeep_slice> : std::true_type - { - }; - } - template - class xkeep_slice : public xslice> + class xkeep_slice { public: @@ -330,7 +377,7 @@ namespace xt template explicit xkeep_slice(C& cont) - requires(!detail::is_xkeep_slice>::value); + requires(!xkeep_slice_concept); explicit xkeep_slice(container_type&& cont); template @@ -385,7 +432,7 @@ namespace xt template inline auto keep(T&& indices) { - if constexpr (xtl::is_integral>::value) + if constexpr (xtl::integral_concept>) { using slice_type = xkeep_slice; using container_type = typename slice_type::container_type; @@ -414,21 +461,8 @@ namespace xt template class xdrop_slice; - namespace detail - { - template - struct is_xdrop_slice : std::false_type - { - }; - - template - struct is_xdrop_slice> : std::true_type - { - }; - } - template - class xdrop_slice : public xslice> + class xdrop_slice { public: @@ -438,7 +472,7 @@ namespace xt template explicit xdrop_slice(C& cont) - requires(!detail::is_xdrop_slice>::value); + requires(!xdrop_slice_concept); explicit xdrop_slice(container_type&& cont); template @@ -494,7 +528,7 @@ namespace xt template inline auto drop(T&& indices) { - if constexpr (xtl::is_integral::value) + if constexpr (xtl::integral_concept) { using slice_type = xdrop_slice; using container_type = typename slice_type::container_type; @@ -533,11 +567,11 @@ namespace xt template auto get(std::size_t size) const { - if constexpr (xtl::is_integral::value && xtl::is_integral::value && xtl::is_integral::value) + if constexpr (xtl::integral_concept && xtl::integral_concept && xtl::integral_concept) { return get_stepped_range(m_start, m_stop, m_step, size); } - else if constexpr (!xtl::is_integral::value && xtl::is_integral::value && xtl::is_integral::value) + else if constexpr (!xtl::integral_concept && xtl::integral_concept && xtl::integral_concept) { return get_stepped_range( m_step > 0 ? 0 : static_cast(size) - 1, @@ -546,30 +580,30 @@ namespace xt size ); } - else if constexpr (xtl::is_integral::value && !xtl::is_integral::value && xtl::is_integral::value) + else if constexpr (xtl::integral_concept && !xtl::integral_concept && xtl::integral_concept) { auto sz = static_cast(size); return get_stepped_range(m_start, m_step > 0 ? sz : -(sz + 1), m_step, size); } - else if constexpr (xtl::is_integral::value && xtl::is_integral::value && !xtl::is_integral::value) + else if constexpr (xtl::integral_concept && xtl::integral_concept && !xtl::integral_concept) { return xrange(normalize(m_start, size), normalize(m_stop, size)); } - else if constexpr (!xtl::is_integral::value && !xtl::is_integral::value && xtl::is_integral::value) + else if constexpr (!xtl::integral_concept && !xtl::integral_concept && xtl::integral_concept) { std::ptrdiff_t start = m_step >= 0 ? 0 : static_cast(size) - 1; std::ptrdiff_t stop = m_step >= 0 ? static_cast(size) : -1; return xstepped_range(start, stop, m_step); } - else if constexpr (xtl::is_integral::value && !xtl::is_integral::value && !xtl::is_integral::value) + else if constexpr (xtl::integral_concept && !xtl::integral_concept && !xtl::integral_concept) { return xrange(normalize(m_start, size), static_cast(size)); } - else if constexpr (!xtl::is_integral::value && xtl::is_integral::value && !xtl::is_integral::value) + else if constexpr (!xtl::integral_concept && xtl::integral_concept && !xtl::integral_concept) { return xrange(0, normalize(m_stop, size)); } - else if constexpr (!xtl::is_integral::value && !xtl::is_integral::value && !xtl::is_integral::value) + else if constexpr (!xtl::integral_concept && !xtl::integral_concept && !xtl::integral_concept) { return xall(static_cast(size)); } @@ -714,11 +748,18 @@ namespace xt template struct cast_if_integer { - using type = std::conditional_t::value, std::ptrdiff_t, T>; + using type = std::conditional_t, std::ptrdiff_t, T>; type operator()(T t) { - return (xtl::is_integral::value) ? static_cast(t) : t; + if constexpr (xtl::integral_concept) + { + return static_cast(t); + } + else + { + return t; + } } }; @@ -778,7 +819,7 @@ namespace xt template inline std::size_t get_size(const S& slice) noexcept { - if constexpr (is_xslice::value) + if constexpr (xslice_concept) { return slice.size(); } @@ -795,7 +836,7 @@ namespace xt template inline std::size_t step_size(const S& slice, std::size_t idx) noexcept { - if constexpr (is_xslice::value) + if constexpr (xslice_concept) { return slice.step_size(idx); } @@ -808,7 +849,7 @@ namespace xt template inline std::size_t step_size(const S& slice, std::size_t idx, std::size_t n) noexcept { - if constexpr (is_xslice::value) + if constexpr (xslice_concept) { return slice.step_size(idx, n); } @@ -823,9 +864,9 @@ namespace xt *********************************************/ template - inline std::size_t value(const S& slice, I i) noexcept + inline auto value(const S& slice, I i) noexcept { - if constexpr (is_xslice::value) + if constexpr (xslice_concept) { using ST = typename S::size_type; return slice(static_cast(i)); @@ -966,22 +1007,6 @@ namespace xt template using get_slice_type = typename detail::get_slice_type_impl>::type; - /************************* - * xslice implementation * - *************************/ - - template - inline auto xslice::derived_cast() noexcept -> derived_type& - { - return *static_cast(this); - } - - template - inline auto xslice::derived_cast() const noexcept -> const derived_type& - { - return *static_cast(this); - } - /************************* * xrange implementation * *************************/ @@ -1283,7 +1308,7 @@ namespace xt template template inline xkeep_slice::xkeep_slice(C& cont) - requires(!detail::is_xkeep_slice>::value) + requires(!xkeep_slice_concept) : m_raw_indices(cont.begin(), cont.end()) { } @@ -1427,7 +1452,7 @@ namespace xt template template inline xdrop_slice::xdrop_slice(C& cont) - requires(!detail::is_xdrop_slice>::value) + requires(!xdrop_slice_concept) : m_raw_indices(cont.begin(), cont.end()) { } diff --git a/include/xtensor/views/xview.hpp b/include/xtensor/views/xview.hpp index ea546d4ff..6ca444044 100644 --- a/include/xtensor/views/xview.hpp +++ b/include/xtensor/views/xview.hpp @@ -135,27 +135,12 @@ namespace xt : false; }; - template - struct is_strided_slice_impl : std::true_type - { - }; - - template - struct is_strided_slice_impl> : std::false_type - { - }; - - template - struct is_strided_slice_impl> : std::false_type - { - }; - // If we have no discontiguous slices, we can calculate strides for this view. template struct is_strided_view : std::integral_constant< bool, - std::conjunction, is_strided_slice_impl>...>::value> + has_data_interface::value && (strided_compatible_concept> && ...)> { }; @@ -713,15 +698,15 @@ namespace xt template ::size_type I, class... Args> size_type index(Args... args) const; - template ::size_type, class T> - size_type sliced_access(const xslice& slice) const; + template ::size_type I, xslice_concept T> + size_type sliced_access(const T& slice) const; - template ::size_type I, class T, class Arg, class... Args> - size_type sliced_access(const xslice& slice, Arg arg, Args... args) const; + template ::size_type I, xslice_concept T, class Arg, class... Args> + size_type sliced_access(const T& slice, Arg arg, Args... args) const; template ::size_type I, class T, class... Args> size_type sliced_access(const T& squeeze, Args...) const - requires(!is_xslice::value); + requires(!xslice_concept); using base_index_type = xindex_type_t; @@ -1657,26 +1642,24 @@ namespace xt } template - template ::size_type I, class T> - inline auto xview::sliced_access(const xslice& slice) const -> size_type + template ::size_type I, xslice_concept T> + inline auto xview::sliced_access(const T& slice) const -> size_type { - return static_cast(slice.derived_cast()(0)); + return static_cast(slice(0)); } template - template ::size_type I, class T, class Arg, class... Args> - inline auto xview::sliced_access(const xslice& slice, Arg arg, Args... args) const -> size_type + template ::size_type I, xslice_concept T, class Arg, class... Args> + inline auto xview::sliced_access(const T& slice, Arg arg, Args... args) const -> size_type { using ST = typename T::size_type; - return static_cast( - slice.derived_cast()(argument(static_cast(arg), static_cast(args)...)) - ); + return static_cast(slice(argument(static_cast(arg), static_cast(args)...))); } template template ::size_type I, class T, class... Args> inline auto xview::sliced_access(const T& squeeze, Args...) const -> size_type - requires(!is_xslice::value) + requires(!xslice_concept) { return static_cast(squeeze); } diff --git a/include/xtensor/views/xview_utils.hpp b/include/xtensor/views/xview_utils.hpp index f74eb07e2..8ea89302f 100644 --- a/include/xtensor/views/xview_utils.hpp +++ b/include/xtensor/views/xview_utils.hpp @@ -50,7 +50,7 @@ namespace xt template inline auto get_slice_value(const S& slice, It& it) noexcept { - if constexpr (is_xslice::value) + if constexpr (xslice_concept) { return slice(typename S::size_type(*it)); }