Skip to content

Commit d3d4245

Browse files
committed
refactor: convert slices from CRTP to C++20 concepts
Use if constexpr with auto return types for slice helper functions.
1 parent abe7b0f commit d3d4245

File tree

4 files changed

+82
-68
lines changed

4 files changed

+82
-68
lines changed

include/xtensor/views/xdynamic_view.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ namespace xt
324324
namespace detail
325325
{
326326
template <class T>
327-
class xfake_slice : public xslice<xfake_slice<T>>
327+
class xfake_slice
328328
{
329329
public:
330330

include/xtensor/views/xslice.hpp

Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef XTENSOR_SLICE_HPP
1111
#define XTENSOR_SLICE_HPP
1212

13+
#include <concepts>
1314
#include <cstddef>
1415
#include <map>
1516
#include <type_traits>
@@ -35,33 +36,73 @@ namespace xt
3536
{
3637

3738
/**********************
38-
* xslice declaration *
39+
* xslice type traits *
3940
**********************/
4041

41-
template <class D>
42-
class xslice
42+
// Forward declarations
43+
template <class T>
44+
class xrange;
45+
46+
template <class T>
47+
class xstepped_range;
48+
49+
template <class T>
50+
class xall;
51+
52+
template <class T>
53+
class xnewaxis;
54+
55+
template <class T>
56+
class xkeep_slice;
57+
58+
template <class T>
59+
class xdrop_slice;
60+
61+
namespace detail
4362
{
44-
public:
63+
template <class S>
64+
struct is_xslice_impl : std::false_type
65+
{
66+
};
67+
68+
template <class T>
69+
struct is_xslice_impl<xrange<T>> : std::true_type
70+
{
71+
};
4572

46-
using derived_type = D;
73+
template <class T>
74+
struct is_xslice_impl<xstepped_range<T>> : std::true_type
75+
{
76+
};
4777

48-
derived_type& derived_cast() noexcept;
49-
const derived_type& derived_cast() const noexcept;
78+
template <class T>
79+
struct is_xslice_impl<xall<T>> : std::true_type
80+
{
81+
};
5082

51-
protected:
83+
template <class T>
84+
struct is_xslice_impl<xnewaxis<T>> : std::true_type
85+
{
86+
};
5287

53-
xslice() = default;
54-
~xslice() = default;
88+
template <class T>
89+
struct is_xslice_impl<xkeep_slice<T>> : std::true_type
90+
{
91+
};
5592

56-
xslice(const xslice&) = default;
57-
xslice& operator=(const xslice&) = default;
93+
template <class T>
94+
struct is_xslice_impl<xdrop_slice<T>> : std::true_type
95+
{
96+
};
97+
}
5898

59-
xslice(xslice&&) = default;
60-
xslice& operator=(xslice&&) = default;
99+
template <class S>
100+
struct is_xslice : detail::is_xslice_impl<S>
101+
{
61102
};
62103

63104
template <class S>
64-
using is_xslice = std::is_base_of<xslice<S>, S>;
105+
concept xslice_concept = is_xslice<S>::value;
65106

66107
template <class... E>
67108
using has_xslice = std::disjunction<is_xslice<E>...>;
@@ -99,7 +140,7 @@ namespace xt
99140
**********************/
100141

101142
template <class T>
102-
class xrange : public xslice<xrange<T>>
143+
class xrange
103144
{
104145
public:
105146

@@ -143,7 +184,7 @@ namespace xt
143184
******************************/
144185

145186
template <class T>
146-
class xstepped_range : public xslice<xstepped_range<T>>
187+
class xstepped_range
147188
{
148189
public:
149190

@@ -188,7 +229,7 @@ namespace xt
188229
********************/
189230

190231
template <class T>
191-
class xall : public xslice<xall<T>>
232+
class xall
192233
{
193234
public:
194235

@@ -259,7 +300,7 @@ namespace xt
259300
************************/
260301

261302
template <class T>
262-
class xnewaxis : public xslice<xnewaxis<T>>
303+
class xnewaxis
263304
{
264305
public:
265306

@@ -320,7 +361,7 @@ namespace xt
320361
}
321362

322363
template <class T>
323-
class xkeep_slice : public xslice<xkeep_slice<T>>
364+
class xkeep_slice
324365
{
325366
public:
326367

@@ -428,7 +469,7 @@ namespace xt
428469
}
429470

430471
template <class T>
431-
class xdrop_slice : public xslice<xdrop_slice<T>>
472+
class xdrop_slice
432473
{
433474
public:
434475

@@ -778,14 +819,11 @@ namespace xt
778819
template <class S>
779820
inline std::size_t get_size(const S& slice) noexcept
780821
{
781-
if constexpr (is_xslice<S>::value)
822+
if constexpr (xslice_concept<S>)
782823
{
783824
return slice.size();
784825
}
785-
else
786-
{
787-
return 1;
788-
}
826+
return 1;
789827
}
790828

791829
/*******************************************************
@@ -795,37 +833,31 @@ namespace xt
795833
template <class S>
796834
inline std::size_t step_size(const S& slice, std::size_t idx) noexcept
797835
{
798-
if constexpr (is_xslice<S>::value)
836+
if constexpr (xslice_concept<S>)
799837
{
800838
return slice.step_size(idx);
801839
}
802-
else
803-
{
804-
return 0;
805-
}
840+
return 0;
806841
}
807842

808843
template <class S>
809844
inline std::size_t step_size(const S& slice, std::size_t idx, std::size_t n) noexcept
810845
{
811-
if constexpr (is_xslice<S>::value)
846+
if constexpr (xslice_concept<S>)
812847
{
813848
return slice.step_size(idx, n);
814849
}
815-
else
816-
{
817-
return 0;
818-
}
850+
return 0;
819851
}
820852

821853
/*********************************************
822854
* homogeneous value for integral and slices *
823855
*********************************************/
824856

825857
template <class S, class I>
826-
inline std::size_t value(const S& slice, I i) noexcept
858+
inline auto value(const S& slice, I i) noexcept
827859
{
828-
if constexpr (is_xslice<S>::value)
860+
if constexpr (xslice_concept<S>)
829861
{
830862
using ST = typename S::size_type;
831863
return slice(static_cast<ST>(i));
@@ -966,22 +998,6 @@ namespace xt
966998
template <class E, class SL>
967999
using get_slice_type = typename detail::get_slice_type_impl<E, std::remove_reference_t<SL>>::type;
9681000

969-
/*************************
970-
* xslice implementation *
971-
*************************/
972-
973-
template <class D>
974-
inline auto xslice<D>::derived_cast() noexcept -> derived_type&
975-
{
976-
return *static_cast<derived_type*>(this);
977-
}
978-
979-
template <class D>
980-
inline auto xslice<D>::derived_cast() const noexcept -> const derived_type&
981-
{
982-
return *static_cast<const derived_type*>(this);
983-
}
984-
9851001
/*************************
9861002
* xrange implementation *
9871003
*************************/

include/xtensor/views/xview.hpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -713,11 +713,11 @@ namespace xt
713713
template <typename std::decay_t<CT>::size_type I, class... Args>
714714
size_type index(Args... args) const;
715715

716-
template <typename std::decay_t<CT>::size_type, class T>
717-
size_type sliced_access(const xslice<T>& slice) const;
716+
template <typename std::decay_t<CT>::size_type I, xslice_concept T>
717+
size_type sliced_access(const T& slice) const;
718718

719-
template <typename std::decay_t<CT>::size_type I, class T, class Arg, class... Args>
720-
size_type sliced_access(const xslice<T>& slice, Arg arg, Args... args) const;
719+
template <typename std::decay_t<CT>::size_type I, xslice_concept T, class Arg, class... Args>
720+
size_type sliced_access(const T& slice, Arg arg, Args... args) const;
721721

722722
template <typename std::decay_t<CT>::size_type I, class T, class... Args>
723723
size_type sliced_access(const T& squeeze, Args...) const
@@ -1657,20 +1657,18 @@ namespace xt
16571657
}
16581658

16591659
template <class CT, class... S>
1660-
template <typename std::decay_t<CT>::size_type I, class T>
1661-
inline auto xview<CT, S...>::sliced_access(const xslice<T>& slice) const -> size_type
1660+
template <typename std::decay_t<CT>::size_type I, xslice_concept T>
1661+
inline auto xview<CT, S...>::sliced_access(const T& slice) const -> size_type
16621662
{
1663-
return static_cast<size_type>(slice.derived_cast()(0));
1663+
return static_cast<size_type>(slice(0));
16641664
}
16651665

16661666
template <class CT, class... S>
1667-
template <typename std::decay_t<CT>::size_type I, class T, class Arg, class... Args>
1668-
inline auto xview<CT, S...>::sliced_access(const xslice<T>& slice, Arg arg, Args... args) const -> size_type
1667+
template <typename std::decay_t<CT>::size_type I, xslice_concept T, class Arg, class... Args>
1668+
inline auto xview<CT, S...>::sliced_access(const T& slice, Arg arg, Args... args) const -> size_type
16691669
{
16701670
using ST = typename T::size_type;
1671-
return static_cast<size_type>(
1672-
slice.derived_cast()(argument<I>(static_cast<ST>(arg), static_cast<ST>(args)...))
1673-
);
1671+
return static_cast<size_type>(slice(argument<I>(static_cast<ST>(arg), static_cast<ST>(args)...)));
16741672
}
16751673

16761674
template <class CT, class... S>

include/xtensor/views/xview_utils.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace xt
5050
template <class S, class It>
5151
inline auto get_slice_value(const S& slice, It& it) noexcept
5252
{
53-
if constexpr (is_xslice<S>::value)
53+
if constexpr (xslice_concept<S>)
5454
{
5555
return slice(typename S::size_type(*it));
5656
}

0 commit comments

Comments
 (0)