Skip to content

Commit 15e77f5

Browse files
committed
Fix constraint for Slice::data()
* ra/base.hh (Slice): As stated. (is_scalar): For std::integral_constant, check the type inside.
1 parent e71afc8 commit 15e77f5

File tree

7 files changed

+1228
-1222
lines changed

7 files changed

+1228
-1222
lines changed

docs/index.html

Lines changed: 1173 additions & 1165 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/ra-ra.texi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
@c http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0834r0.html
1010
@c http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0573r2.html
1111
@c http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0356r2.html
12-
@c References to source [ma··] or [ma···] current last is 117.
12+
@c References to source [ma··] or [ma···] current last is 118.
1313

1414
@set VERSION 31
15-
@set UPDATED 2025 September 09
15+
@set UPDATED 2026 February 2
1616

1717
@copying
1818
@code{ra::} (version @value{VERSION}, updated @value{UPDATED})
@@ -1027,7 +1027,7 @@ cout << f(b(0, 0)) << endl; // ok, automatic conversion from ViewBig<T *> to T &
10271027
@end verbatim
10281028
@end example
10291029

1030-
The result of @code{A(i, ...)} when @code{A} is a view, or equivalently @code{@ref{x-from,@code{from}}(A, i ...)}, is itself be a view when
1030+
The result of @code{A(i, ...)} when @code{A} is a view, or equivalently @code{@ref{x-from,@code{from}}(A, i ...)}, is itself a view when
10311031
@itemize
10321032
@item
10331033
each of the @code{i ...} is @emph{beatable}, that is, either

ra/arrays.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct ViewSmall
100100
}
101101
// T not is_scalar [ra44]
102102
constexpr ViewSmall const & operator=(T const & t) const { ra::iter(*this) = ra::scalar(t); return *this; }
103-
// cf RA_ASSIGNOPS_ITER [ra38] [ra34]
103+
// cf RA_ASSIGNOPS_ITER [ra38][ra34]
104104
ViewSmall const & operator=(ViewSmall const & x) const { ra::iter(*this) = x; return *this; }
105105
#define RA_ASSIGNOPS(OP) \
106106
constexpr ViewSmall const & operator OP(auto const & x) const { ra::iter(*this) OP x; return *this; } \
@@ -309,7 +309,7 @@ struct ViewBig
309309
#undef RA_BRACES
310310
// T not is_scalar [ra44]
311311
constexpr ViewBig const & operator=(T const & t) const { ra::iter(*this) = ra::scalar(t); return *this; }
312-
// cf RA_ASSIGNOPS_ITER [ra38] [ra34]
312+
// cf RA_ASSIGNOPS_ITER [ra38][ra34]
313313
ViewBig const & operator=(ViewBig const & x) const { ra::iter(*this) = x; return *this; }
314314
#define RA_ASSIGNOPS(OP) \
315315
constexpr ViewBig const & operator OP (auto const & x) const { ra::iter(*this) OP x; return *this; } \

ra/base.hh

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ struct complement_sorted_list_<tuple<S0, S ...>, tuple<T0, T ...>>
210210
using type = cons<T0, complement_sorted_list<tuple<S0, S ...>, tuple<T ...>>>;
211211
};
212212

213-
// Like complement_list where the second argument is [0 .. end-1].
213+
// Like complement_list where the second arg is [0 .. end-1].
214214
template <class S, int end> using complement = complement_sorted_list<S, iota<end>>;
215215

216216
// Prepend element to each of a list of lists.
@@ -277,10 +277,9 @@ struct mapanticomb<std::tuple<C ...>, D>
277277
using type = std::tuple<typename anticomb<C, D>::type ...>;
278278
};
279279

280-
template <int D, int O>
281-
struct choose_
280+
template <int D, int O> struct choose_
282281
{
283-
static_assert(D>=O, "Bad dimension or form order.");
282+
static_assert(D>=O, "Bad args to choose_.");
284283
using type = combs<iota<D>, O>;
285284
};
286285

@@ -289,7 +288,7 @@ template <int D, int O> using choose = typename choose_<D, O>::type;
289288
template <int D, int O> requires ((D>1) && (2*O>D))
290289
struct choose_<D, O>
291290
{
292-
static_assert(D>=O, "Bad dimension or form order.");
291+
static_assert(D>=O, "Bad args to choose_.");
293292
using type = typename mapanticomb<choose<D, D-O>, D>::type;
294293
};
295294

@@ -342,15 +341,41 @@ struct default_init_allocator: public A
342341

343342
template <class T> using vector_default_init = std::vector<T, default_init_allocator<T>>;
344343

344+
// FIXME c++26 p2841 ?
345+
#define RA_IS_DEF(NAME, PRED) \
346+
template <class A> constexpr bool RA_JOIN(NAME, _def) = requires { requires PRED; }; \
347+
template <class A> concept NAME = RA_JOIN(NAME, _def)<std::decay_t< A >>;
348+
349+
// Contextual len, a unique object.
350+
constexpr struct Len
351+
{
352+
consteval static rank_t rank() { return 0; }
353+
[[noreturn]] consteval static void len_out_of_context() { std::abort(); }
354+
consteval static dim_t len_s(int k) { len_out_of_context(); }
355+
consteval static dim_t len(int k) { len_out_of_context(); }
356+
consteval static dim_t step(int k) { len_out_of_context(); }
357+
consteval static void adv(rank_t k, dim_t d) { len_out_of_context(); }
358+
consteval static bool keep(dim_t st, int z, int j) { len_out_of_context(); }
359+
consteval dim_t operator*() const { len_out_of_context(); }
360+
consteval static int save() { len_out_of_context(); }
361+
consteval static void load(int) { len_out_of_context(); }
362+
consteval static void mov(dim_t d) { len_out_of_context(); }
363+
} len;
364+
365+
template <class E> struct WLen; // defined in ply.hh. FIXME C++ p2481
366+
template <class E> concept has_len = requires(int ln, E && e) { WLen<std::decay_t<E>>::f(ln, RA_FW(e)); };
367+
RA_IS_DEF(is_special, false) // rank-0 types that we don't want reduced.
368+
template <has_len E> constexpr bool is_special_def<E> = true;
369+
345370
template <class A>
346-
concept Iterator = requires (A a, rank_t k, dim_t d, rank_t i, rank_t j)
371+
concept Iterator = requires (A a, rank_t k, dim_t d, rank_t i)
347372
{
348373
{ a.rank() } -> std::same_as<rank_t>;
349374
{ std::decay_t<A>::len_s(k) } -> std::same_as<dim_t>;
350375
{ a.len(k) } -> std::same_as<dim_t>;
351376
{ a.adv(k, d) } -> std::same_as<void>;
352377
{ a.step(k) };
353-
{ a.keep(d, i, j) } -> std::same_as<bool>;
378+
{ a.keep(d, k, i) } -> std::same_as<bool>;
354379
{ a.save() };
355380
{ a.load(std::declval<decltype(a.save())>()) } -> std::same_as<void>;
356381
{ a.mov(d) } -> std::same_as<void>;
@@ -362,16 +387,12 @@ concept Slice = requires (A a)
362387
{
363388
{ a.rank() } -> std::same_as<rank_t>;
364389
{ a.iter() } -> Iterator;
365-
{ a.data() }; // -> has_len || std::bidirectional_iterator;
390+
requires has_len<decltype(a.data())> || std::bidirectional_iterator<decltype(a.data())>;
366391
{ a.dimv };
367392
};
368393

369-
// FIXME c++26 p2841 ?
370-
#define RA_IS_DEF(NAME, PRED) \
371-
template <class A> constexpr bool RA_JOIN(NAME, _def) = requires { requires PRED; }; \
372-
template <class A> concept NAME = RA_JOIN(NAME, _def)<std::decay_t< A >>;
373-
374-
RA_IS_DEF(is_scalar, !std::is_pointer_v<A> && std::is_scalar_v<A> || is_ctype<A>)
394+
RA_IS_DEF(is_scalar, !std::is_pointer_v<A> && std::is_scalar_v<A>);
395+
template <class T, T v> constexpr bool is_scalar_def<std::integral_constant<T, v>> = is_scalar<T>;
375396
template <> constexpr bool is_scalar_def<std::strong_ordering> = true;
376397
template <> constexpr bool is_scalar_def<std::weak_ordering> = true;
377398
template <> constexpr bool is_scalar_def<std::partial_ordering> = true;
@@ -414,10 +435,9 @@ rank(auto const & v)
414435
}
415436
}
416437

417-
// all args rank 0 (apply immediately), but at least one ra:: (disambiguate scalar version).
438+
// All args rank 0 (apply immediately), but at least one ra:: (disambiguate scalar version).
418439
template <class A> concept is_ra_pos = is_ra<A> && 0!=rank_s<A>();
419440
template <class A> concept is_ra_0 = (is_ra<A> && 0==rank_s<A>()) || is_scalar<A>;
420-
RA_IS_DEF(is_special, false) // rank-0 types that we don't want reduced.
421441
template <class ... A> constexpr bool toreduce = (!is_scalar<A> || ...) && ((is_ra_0<A> && !is_special<A>) && ...);
422442
template <class ... A> constexpr bool tomap = ((is_ra_pos<A> || is_special<A>) || ...) && ((is_ra<A> || is_scalar<A> || is_fov<A> || is_builtin<A>) && ...);
423443

ra/expr.hh

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -59,39 +59,6 @@ namespace ra {
5959
constexpr TYPE(TYPE const & x) = default; \
6060
RA_FE(RA_ASSIGNOPS_DEFAULT, =, *=, +=, -=, /=)
6161

62-
// Contextual len, a unique object. See wlen in arrays.hh
63-
64-
constexpr struct Len
65-
{
66-
consteval static rank_t rank() { return 0; }
67-
[[noreturn]] consteval static void len_out_of_context() { std::abort(); }
68-
consteval static dim_t len_s(int k) { len_out_of_context(); }
69-
consteval static dim_t len(int k) { len_out_of_context(); }
70-
consteval static dim_t step(int k) { len_out_of_context(); }
71-
consteval static void adv(rank_t k, dim_t d) { len_out_of_context(); }
72-
consteval static bool keep(dim_t st, int z, int j) { len_out_of_context(); }
73-
consteval dim_t operator*() const { len_out_of_context(); }
74-
consteval static int save() { len_out_of_context(); }
75-
consteval static void load(int) { len_out_of_context(); }
76-
consteval static void mov(dim_t d) { len_out_of_context(); }
77-
} len;
78-
79-
template <class E> struct WLen; // defined in ply.hh. FIXME C++ p2481
80-
template <class E> concept has_len = requires(int ln, E && e) { WLen<std::decay_t<E>>::f(ln, RA_FW(e)); };
81-
template <has_len E> constexpr bool is_special_def<E> = true; // protect exprs with Len from reduction.
82-
83-
template <class Ln, class E>
84-
constexpr decltype(auto)
85-
wlen(Ln ln, E && e)
86-
{
87-
static_assert(std::is_integral_v<Ln> || is_ctype<Ln>);
88-
if constexpr (has_len<E>) {
89-
return WLen<std::decay_t<E>>::f(ln, RA_FW(e));
90-
} else {
91-
return RA_FW(e);
92-
}
93-
}
94-
9562
template <class N> constexpr auto
9663
maybe_any = []{ if constexpr (is_ctype<N>) { return N::value; } else { return ANY; } }();
9764

@@ -147,7 +114,7 @@ struct Scalar final
147114
constexpr static void adv(rank_t k, dim_t d) {}
148115
constexpr static bool keep(dim_t st, int z, int j) { return true; }
149116
constexpr decltype(auto) at(auto && i) const { return c; }
150-
constexpr std::conditional_t<std::is_lvalue_reference_v<C>, C, C const &> operator*() const { return c; } // [ra24] [ra37] [ra39]
117+
constexpr std::conditional_t<std::is_lvalue_reference_v<C>, C, C const &> operator*() const { return c; } // [ra24][ra37][ra39]
151118
consteval static int save() { return 0; }
152119
constexpr static void load(int) {}
153120
constexpr static void mov(dim_t d) {}
@@ -165,7 +132,6 @@ constexpr decltype(auto) iter(is_iterator auto && a) { return RA_FW(a); }
165132
// Cell doesn't retain rvalues [ra4]. If both Slice and Iterator (Ptr), go as Iterator.
166133
// TODO any exprs? runtime cr? ra::len in cr?
167134
template <int cr=0> constexpr auto iter(Slice auto && a) requires (!is_iterator<decltype(a)>) { return RA_FW(a).template iter<cr>(); }
168-
169135
// forward decl.
170136
constexpr auto iter(is_fov auto && a);
171137
constexpr auto iter(is_builtin auto && a);

ra/ply.hh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,18 @@ constexpr auto range(is_ra auto && a) requires (requires { a.begin(); }) { stati
247247
// Replace Len in expr tree. VAL arguments that must be either is_ctype or is_scalar.
248248
// ---------------------
249249

250+
template <class Ln, class E>
251+
constexpr decltype(auto)
252+
wlen(Ln ln, E && e)
253+
{
254+
static_assert(std::is_integral_v<Ln> || is_ctype<Ln>);
255+
if constexpr (has_len<E>) {
256+
return WLen<std::decay_t<E>>::f(ln, RA_FW(e));
257+
} else {
258+
return RA_FW(e);
259+
}
260+
}
261+
250262
template <>
251263
struct WLen<Len>
252264
{

test/cellptr.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
#if 0==RA_CHECK
1111
#undef RA_CHECK
12+
#define RA_CHECK 1 // required by 'regression from test/checks' below
1213
#endif
13-
#define RA_CHECK 1 // required by 'regression from test/checks' below
1414

1515
#include <iostream>
1616
#include "ra/base.hh"

0 commit comments

Comments
 (0)