Skip to content

Commit fce460b

Browse files
refactor(expression): use std::invoke and add types to functional objects to catch type errors
1 parent 51674d5 commit fce460b

File tree

2 files changed

+57
-32
lines changed

2 files changed

+57
-32
lines changed

include/boost/numeric/ublas/tensor/expression.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ struct binary_tensor_expression
181181
[[nodiscard]] constexpr auto const& left_expr() const noexcept{ return cast_tensor_expression(el); }
182182
[[nodiscard]] constexpr auto const& right_expr() const noexcept{ return cast_tensor_expression(er); }
183183

184-
[[nodiscard]] inline
185-
constexpr decltype(auto) operator()(size_type i) const { return op(left_expr()(i), right_expr()(i)); }
184+
[[nodiscard]] inline constexpr
185+
decltype(auto) operator()(size_type i) const { return std::invoke(op, left_expr()(i), right_expr()(i)); }
186186

187187
protected:
188188
/**
@@ -255,7 +255,7 @@ struct unary_tensor_expression
255255
[[nodiscard]] constexpr auto const& expr() const noexcept{ return cast_tensor_expression(e); }
256256

257257
[[nodiscard]] inline constexpr
258-
decltype(auto) operator()(size_type i) const { return op(expr()(i)); }
258+
decltype(auto) operator()(size_type i) const { return std::invoke(op, expr()(i)); }
259259

260260
protected:
261261
/**

include/boost/numeric/ublas/tensor/operators_arithmetic.hpp

+54-29
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ inline
7676
constexpr auto operator*( EL&& lhs, ER&& rhs ) noexcept
7777
{
7878
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
79+
using value_type = typename tensor_type::value_type;
7980

8081
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
81-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::multiplies<>{}
82+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::multiplies<value_type>{}
8283
);
8384
}
8485

@@ -91,9 +92,10 @@ inline
9192
constexpr auto operator+( EL&& lhs, ER&& rhs ) noexcept
9293
{
9394
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
95+
using value_type = typename tensor_type::value_type;
9496

9597
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
96-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::plus<>{}
98+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::plus<value_type>{}
9799
);
98100
}
99101

@@ -106,9 +108,10 @@ inline
106108
constexpr auto operator-( EL&& lhs, ER&& rhs ) noexcept
107109
{
108110
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
111+
using value_type = typename tensor_type::value_type;
109112

110113
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
111-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::minus<>{}
114+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::minus<value_type>{}
112115
);
113116
}
114117

@@ -121,9 +124,10 @@ inline
121124
constexpr auto operator/( EL&& lhs, ER&& rhs ) noexcept
122125
{
123126
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
127+
using value_type = typename tensor_type::value_type;
124128

125129
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
126-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::divides<>{}
130+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::divides<value_type>{}
127131
);
128132
}
129133

@@ -136,9 +140,10 @@ inline
136140
constexpr auto operator*( EL&& lhs, ER&& rhs ) noexcept
137141
{
138142
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
143+
using value_type = typename tensor_type::value_type;
139144

140145
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
141-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::multiplies<>{}
146+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::multiplies<value_type>{}
142147
);
143148
}
144149

@@ -151,9 +156,10 @@ inline
151156
constexpr auto operator+( EL&& lhs, ER&& rhs ) noexcept
152157
{
153158
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
159+
using value_type = typename tensor_type::value_type;
154160

155161
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
156-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::plus<>{}
162+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::plus<value_type>{}
157163
);
158164
}
159165

@@ -166,9 +172,10 @@ inline
166172
constexpr auto operator-( EL&& lhs, ER&& rhs ) noexcept
167173
{
168174
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
175+
using value_type = typename tensor_type::value_type;
169176

170177
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
171-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::minus<>{}
178+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::minus<value_type>{}
172179
);
173180
}
174181

@@ -180,9 +187,10 @@ template <typename EL, typename ER>
180187
inline constexpr auto operator/( EL&& lhs, ER&& rhs ) noexcept
181188
{
182189
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
190+
using value_type = typename tensor_type::value_type;
183191

184192
return boost::numeric::ublas::detail::make_binary_tensor_expression<tensor_type>(
185-
std::forward<EL>(lhs), std::forward<ER>(rhs), std::divides<>{}
193+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::divides<value_type>{}
186194
);
187195
}
188196

@@ -204,7 +212,7 @@ inline constexpr auto operator+( EL&& lhs, ER&& rhs ) noexcept
204212
);
205213

206214
return boost::numeric::ublas::detail::make_binary_tensor_expression<ltensor_t> (
207-
std::forward<EL>(lhs), std::forward<ER>(rhs), [](auto const& l, auto const& r){ return l + r; }
215+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::plus<lvalue_t>{}
208216
);
209217
}
210218

@@ -227,7 +235,7 @@ inline constexpr auto operator-( EL&& lhs, ER&& rhs ) noexcept
227235
);
228236

229237
return boost::numeric::ublas::detail::make_binary_tensor_expression<ltensor_t> (
230-
std::forward<EL>(lhs), std::forward<ER>(rhs), [](auto const& l, auto const& r){ return l - r; }
238+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::minus<lvalue_t>{}
231239
);
232240
}
233241

@@ -249,7 +257,7 @@ inline constexpr auto operator*( EL&& lhs, ER&& rhs ) noexcept
249257
);
250258

251259
return boost::numeric::ublas::detail::make_binary_tensor_expression<ltensor_t> (
252-
std::forward<EL>(lhs), std::forward<ER>(rhs), [](auto const& l, auto const& r){ return l * r; }
260+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::multiplies<lvalue_t>{}
253261
);
254262
}
255263

@@ -271,7 +279,7 @@ inline constexpr auto operator/( EL&& lhs, ER&& rhs ) noexcept
271279
);
272280

273281
return boost::numeric::ublas::detail::make_binary_tensor_expression<ltensor_t> (
274-
std::forward<EL>(lhs), std::forward<ER>(rhs), [](auto const& l, auto const& r){ return l / r; }
282+
std::forward<EL>(lhs), std::forward<ER>(rhs), std::divides<lvalue_t>{}
275283
);
276284
}
277285

@@ -284,10 +292,11 @@ inline constexpr auto operator+(
284292
ER&& rhs
285293
) noexcept {
286294
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
295+
using value_type = typename tensor_type::value_type;
287296

288297
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
289298
std::forward<ER>(rhs),
290-
[lhs](auto const& r){ return lhs + r; }
299+
[lhs](value_type const& r){ return lhs + r; }
291300
);
292301
}
293302

@@ -298,10 +307,11 @@ inline constexpr auto operator-(
298307
ER&& rhs
299308
) noexcept {
300309
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
310+
using value_type = typename tensor_type::value_type;
301311

302312
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
303313
std::forward<ER>(rhs),
304-
[lhs](auto const& r){ return lhs - r; }
314+
[lhs](value_type const& r){ return lhs - r; }
305315
);
306316
}
307317

@@ -312,10 +322,11 @@ inline constexpr auto operator*(
312322
ER&& rhs
313323
) noexcept {
314324
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
325+
using value_type = typename tensor_type::value_type;
315326

316327
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
317328
std::forward<ER>(rhs),
318-
[lhs](auto const& r){ return lhs * r; }
329+
[lhs](value_type const& r){ return lhs * r; }
319330
);
320331
}
321332

@@ -326,10 +337,11 @@ inline constexpr auto operator/(
326337
ER&& rhs
327338
) noexcept {
328339
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<ER>;
340+
using value_type = typename tensor_type::value_type;
329341

330342
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
331343
std::forward<ER>(rhs),
332-
[lhs](auto const& r){ return lhs / r; }
344+
[lhs](value_type const& r){ return lhs / r; }
333345
);
334346
}
335347

@@ -340,10 +352,11 @@ inline constexpr auto operator+(
340352
typename boost::numeric::ublas::detail::real_expression_type_t<EL>::value_type rhs
341353
) noexcept {
342354
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
355+
using value_type = typename tensor_type::value_type;
343356

344357
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
345358
std::forward<EL>(lhs),
346-
[rhs] (auto const& l) { return l + rhs; }
359+
[rhs] (value_type const& l) { return l + rhs; }
347360
);
348361
}
349362

@@ -354,10 +367,11 @@ inline constexpr auto operator-(
354367
typename boost::numeric::ublas::detail::real_expression_type_t<EL>::value_type rhs
355368
) noexcept {
356369
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
370+
using value_type = typename tensor_type::value_type;
357371

358372
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
359373
std::forward<EL>(lhs),
360-
[rhs] (auto const& l) { return l - rhs; }
374+
[rhs] (value_type const& l) { return l - rhs; }
361375
);
362376
}
363377

@@ -368,10 +382,11 @@ inline constexpr auto operator*(
368382
typename boost::numeric::ublas::detail::real_expression_type_t<EL>::value_type rhs
369383
) noexcept {
370384
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
385+
using value_type = typename tensor_type::value_type;
371386

372387
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
373388
std::forward<EL>(lhs),
374-
[rhs] (auto const& l) { return l * rhs; }
389+
[rhs] (value_type const& l) { return l * rhs; }
375390
);
376391
}
377392

@@ -382,10 +397,11 @@ inline constexpr auto operator/(
382397
typename boost::numeric::ublas::detail::real_expression_type_t<EL>::value_type rhs
383398
) noexcept {
384399
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<EL>;
400+
using value_type = typename tensor_type::value_type;
385401

386402
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
387403
std::forward<EL>(lhs),
388-
[rhs] (auto const& l) { return l / rhs; }
404+
[rhs] (value_type const& l) { return l / rhs; }
389405
);
390406
}
391407

@@ -394,7 +410,8 @@ inline constexpr auto& operator += (
394410
boost::numeric::ublas::tensor_core<T>& lhs,
395411
boost::numeric::ublas::detail::tensor_expression<boost::numeric::ublas::tensor_core<T>,D> const& expr
396412
){
397-
boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l+=r; } );
413+
using value_type = typename boost::numeric::ublas::tensor_core<T>::value_type;
414+
boost::numeric::ublas::detail::eval(lhs, expr(), [](value_type& l, value_type const& r) { l+=r; } );
398415
return lhs;
399416
}
400417

@@ -403,7 +420,8 @@ inline constexpr auto& operator -= (
403420
boost::numeric::ublas::tensor_core<T>& lhs,
404421
const boost::numeric::ublas::detail::tensor_expression<boost::numeric::ublas::tensor_core<T>,D> &expr
405422
){
406-
boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l-=r; } );
423+
using value_type = typename boost::numeric::ublas::tensor_core<T>::value_type;
424+
boost::numeric::ublas::detail::eval(lhs, expr(), [](value_type& l, value_type const& r) { l-=r; } );
407425
return lhs;
408426
}
409427

@@ -412,7 +430,8 @@ inline constexpr auto& operator *= (
412430
boost::numeric::ublas::tensor_core<T>& lhs,
413431
const boost::numeric::ublas::detail::tensor_expression<boost::numeric::ublas::tensor_core<T>,D> &expr
414432
){
415-
boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l*=r; } );
433+
using value_type = typename boost::numeric::ublas::tensor_core<T>::value_type;
434+
boost::numeric::ublas::detail::eval(lhs, expr(), [](value_type& l, value_type const& r) { l*=r; } );
416435
return lhs;
417436
}
418437

@@ -421,7 +440,8 @@ inline constexpr auto& operator /= (
421440
boost::numeric::ublas::tensor_core<T>& lhs,
422441
const boost::numeric::ublas::detail::tensor_expression<boost::numeric::ublas::tensor_core<T>,D> &expr
423442
){
424-
boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l/=r; } );
443+
using value_type = typename boost::numeric::ublas::tensor_core<T>::value_type;
444+
boost::numeric::ublas::detail::eval(lhs, expr(), [](value_type& l, value_type const& r) { l/=r; } );
425445
return lhs;
426446
}
427447

@@ -433,7 +453,8 @@ inline constexpr auto& operator += (
433453
boost::numeric::ublas::tensor_core<TensorEngine>& lhs,
434454
typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type r
435455
){
436-
boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l+=r; } );
456+
using value_type = typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type;
457+
boost::numeric::ublas::detail::eval(lhs, [r](value_type& l) { l+=r; } );
437458
return lhs;
438459
}
439460

@@ -442,7 +463,8 @@ inline constexpr auto& operator -= (
442463
boost::numeric::ublas::tensor_core<TensorEngine>& lhs,
443464
typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type r
444465
){
445-
boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l-=r; } );
466+
using value_type = typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type;
467+
boost::numeric::ublas::detail::eval(lhs, [r](value_type& l) { l-=r; } );
446468
return lhs;
447469
}
448470

@@ -451,7 +473,8 @@ inline constexpr auto& operator *= (
451473
boost::numeric::ublas::tensor_core<TensorEngine>& lhs,
452474
typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type r
453475
){
454-
boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l*=r; } );
476+
using value_type = typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type;
477+
boost::numeric::ublas::detail::eval(lhs, [r](value_type& l) { l*=r; } );
455478
return lhs;
456479
}
457480

@@ -460,7 +483,8 @@ inline constexpr auto& operator /= (
460483
boost::numeric::ublas::tensor_core<TensorEngine>& lhs,
461484
typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type r
462485
){
463-
boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l/=r; } );
486+
using value_type = typename boost::numeric::ublas::tensor_core<TensorEngine>::value_type;
487+
boost::numeric::ublas::detail::eval(lhs, [r](value_type& l) { l/=r; } );
464488
return lhs;
465489
}
466490

@@ -476,8 +500,9 @@ template<typename E>
476500
requires boost::numeric::ublas::detail::TensorExpression<E>
477501
inline constexpr auto operator -(E&& e) {
478502
using tensor_type = boost::numeric::ublas::detail::real_expression_type_t<E>;
503+
using value_type = typename tensor_type::value_type;
479504
return boost::numeric::ublas::detail::make_unary_tensor_expression<tensor_type> (
480-
std::forward<E>(e), std::negate<>{}
505+
std::forward<E>(e), std::negate<value_type>{}
481506
);
482507
}
483508

0 commit comments

Comments
 (0)