Skip to content

Commit cbd899d

Browse files
Merge pull request #1401 from PowerGridModel/pgm/remove-forward
Improve and reduce usage of universal reference and forward
2 parents f27bc26 + ea2d567 commit cbd899d

31 files changed

Lines changed: 247 additions & 242 deletions

power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/dataset.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,14 @@ template <dataset_type_tag dataset_type_> class Dataset {
553553
return result;
554554
}
555555

556-
template <class type_getter, class ComponentType, typename Func,
556+
template <class type_getter, class ComponentType, functor_c Func,
557557
class StructType = DataStruct<typename type_getter::template type<ComponentType>>>
558558
requires std::invocable<Func, SpanRange<StructType>> && std::invocable<Func, RangeObject<StructType>>
559-
auto for_each_component(Func&& func, Idx scenario = invalid_index) const {
559+
auto for_each_component(Func func, Idx scenario = invalid_index) const {
560560
if (is_columnar(ComponentType::name)) {
561-
return std::forward<Func>(func)(get_columnar_buffer_span<type_getter, ComponentType, StructType>(scenario));
561+
return func(get_columnar_buffer_span<type_getter, ComponentType, StructType>(scenario));
562562
}
563-
return std::forward<Func>(func)(get_buffer_span<type_getter, ComponentType, StructType>(scenario));
563+
return func(get_buffer_span<type_getter, ComponentType, StructType>(scenario));
564564
}
565565

566566
void set_next_cartesian_product_dimension(Dataset const* next) {

power_grid_model_c/power_grid_model/include/power_grid_model/auxiliary/meta_data.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,18 @@ template <class T> constexpr CType ctype_v = ctype_t<T>::value;
5151
// function selector based on ctype
5252
// the operator() of the functor should have a single template parameter
5353
// the selector will instantiate the operator() with relevant type
54-
template <class Functor, class... Args> decltype(auto) ctype_func_selector(CType ctype, Functor&& f, Args&&... args) {
54+
template <functor_c Functor, class... Args> decltype(auto) ctype_func_selector(CType ctype, Functor f, Args&&... args) {
5555
using enum CType;
5656

5757
switch (ctype) {
5858
case c_double:
59-
return std::forward<Functor>(f).template operator()<double>(std::forward<Args>(args)...);
59+
return f.template operator()<double>(std::forward<Args>(args)...);
6060
case c_double3:
61-
return std::forward<Functor>(f).template operator()<RealValue<asymmetric_t>>(std::forward<Args>(args)...);
61+
return f.template operator()<RealValue<asymmetric_t>>(std::forward<Args>(args)...);
6262
case c_int8:
63-
return std::forward<Functor>(f).template operator()<int8_t>(std::forward<Args>(args)...);
63+
return f.template operator()<int8_t>(std::forward<Args>(args)...);
6464
case c_int32:
65-
return std::forward<Functor>(f).template operator()<int32_t>(std::forward<Args>(args)...);
65+
return f.template operator()<int32_t>(std::forward<Args>(args)...);
6666
default:
6767
throw MissingCaseForEnumError{"CType selector", ctype};
6868
}

power_grid_model_c/power_grid_model/include/power_grid_model/calculation.hpp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,55 +26,53 @@ struct short_circuit_t : calculation_type_t {};
2626
template <typename T>
2727
concept calculation_type_tag = std::derived_from<T, calculation_type_t>;
2828

29-
template <class Functor, class... Args>
30-
decltype(auto) calculation_symmetry_func_selector(CalculationSymmetry calculation_symmetry, Functor&& f,
29+
template <class... Args>
30+
decltype(auto) calculation_symmetry_func_selector(CalculationSymmetry calculation_symmetry, functor_c auto f,
3131
Args&&... args) {
3232
using enum CalculationSymmetry;
3333

3434
switch (calculation_symmetry) {
3535
case symmetric:
36-
return std::forward<Functor>(f).template operator()<symmetric_t>(std::forward<Args>(args)...);
36+
return f.template operator()<symmetric_t>(std::forward<Args>(args)...);
3737
case asymmetric:
38-
return std::forward<Functor>(f).template operator()<asymmetric_t>(std::forward<Args>(args)...);
38+
return f.template operator()<asymmetric_t>(std::forward<Args>(args)...);
3939
default:
4040
throw MissingCaseForEnumError{"Calculation symmetry selector", calculation_symmetry};
4141
}
4242
}
4343

44-
template <class Functor, class... Args>
45-
decltype(auto) calculation_type_func_selector(CalculationType calculation_type, Functor&& f, Args&&... args) {
44+
template <class... Args>
45+
decltype(auto) calculation_type_func_selector(CalculationType calculation_type, functor_c auto f, Args&&... args) {
4646
using enum CalculationType;
4747

4848
switch (calculation_type) {
4949
case CalculationType::power_flow:
50-
return std::forward<Functor>(f).template operator()<power_flow_t>(std::forward<Args>(args)...);
50+
return f.template operator()<power_flow_t>(std::forward<Args>(args)...);
5151
case CalculationType::state_estimation:
52-
return std::forward<Functor>(f).template operator()<state_estimation_t>(std::forward<Args>(args)...);
52+
return f.template operator()<state_estimation_t>(std::forward<Args>(args)...);
5353
case CalculationType::short_circuit:
54-
return std::forward<Functor>(f).template operator()<short_circuit_t>(std::forward<Args>(args)...);
54+
return f.template operator()<short_circuit_t>(std::forward<Args>(args)...);
5555
default:
5656
throw MissingCaseForEnumError{"CalculationType", calculation_type};
5757
}
5858
}
5959

60-
template <class Functor, class... Args>
60+
template <class... Args>
6161
decltype(auto) calculation_type_symmetry_func_selector(CalculationType calculation_type,
62-
CalculationSymmetry calculation_symmetry, Functor&& f,
62+
CalculationSymmetry calculation_symmetry, functor_c auto f,
6363
Args&&... args) {
6464
calculation_type_func_selector(
6565
calculation_type,
66-
[]<calculation_type_tag calculation_type, typename Functor_, typename... Args_>(
67-
CalculationSymmetry calculation_symmetry_, Functor_&& f_, Args_&&... args_) {
66+
[]<calculation_type_tag calculation_type, typename... Args_>(CalculationSymmetry calculation_symmetry_,
67+
functor_c auto f_, Args_&&... args_) {
6868
calculation_symmetry_func_selector(
6969
calculation_symmetry_,
70-
[]<symmetry_tag sym, typename SubFunctor, typename... SubArgs>(SubFunctor&& sub_f,
71-
SubArgs&&... sub_args) {
72-
std::forward<SubFunctor>(sub_f).template operator()<calculation_type, sym>(
73-
std::forward<SubArgs>(sub_args)...);
70+
[]<symmetry_tag sym, typename... SubArgs>(functor_c auto sub_f, SubArgs&&... sub_args) {
71+
sub_f.template operator()<calculation_type, sym>(std::forward<SubArgs>(sub_args)...);
7472
},
75-
std::forward<Functor_>(f_), std::forward<Args_>(args_)...);
73+
f_, std::forward<Args_>(args_)...);
7674
},
77-
calculation_symmetry, std::forward<Functor>(f), std::forward<Args>(args)...);
75+
calculation_symmetry, f, std::forward<Args>(args)...);
7876
}
7977

8078
template <typename T, typename sym> struct Calculator;

power_grid_model_c/power_grid_model/include/power_grid_model/common/calculation_info.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,8 @@ class CalculationInfo : public Logger {
3636
void log(LogEvent tag, double value) override { log_impl(tag, value); }
3737
void log(LogEvent tag, Idx value) override { log_impl(tag, static_cast<double>(value)); }
3838
void log(std::string_view /*message*/) const { /* ignore all such events for now */ }
39-
template <LazyLoggingFn Fn> void log(LogEvent /*tag*/, Fn&& fn) const {
40-
capturing::into_the_void(std::forward<Fn>(fn));
41-
}
42-
template <LazyLoggingFn Fn> void log(Fn&& fn) const { capturing::into_the_void(std::forward<Fn>(fn)); }
39+
template <LazyLoggingFn Fn> void log(LogEvent /*tag*/, Fn /*fn*/) const { /*do nothing*/ }
40+
template <LazyLoggingFn Fn> void log(Fn /*fn*/) const { /*do nothing*/ }
4341

4442
private:
4543
Data data_;

power_grid_model_c/power_grid_model/include/power_grid_model/common/common.hpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include <functional>
1414
#include <limits>
1515
#include <numbers>
16+
#include <ranges>
1617
#include <type_traits>
18+
#include <utility>
1719
#include <vector>
1820

1921
namespace power_grid_model {
@@ -101,22 +103,38 @@ template <class T, class... Ts>
101103
concept derives_from_any_in_list_c = (std::derived_from<T, Ts> || ...);
102104

103105
namespace capturing {
104-
// perfect forward into void
105-
template <class... T>
106-
constexpr void into_the_void(T&&... /*ignored*/) { // NOLINT(cppcoreguidelines-missing-std-forward)
106+
// capture into void
107+
template <class... T> constexpr void into_the_void(T const&... /*ignored*/) {
107108
// do nothing; the constexpr allows all compilers to optimize this away
108109
}
109110
} // namespace capturing
110111

111112
// functor to include all
112113
struct IncludeAll {
113-
template <class... T> consteval bool operator()(T&&... args) const {
114-
capturing::into_the_void(std::forward<T>(args)...);
115-
return true;
116-
}
114+
template <class... T> consteval bool operator()(T const&... /* args */) const { return true; }
117115
};
118116
constexpr IncludeAll include_all{};
119117

118+
// define a non-owning view
119+
namespace detail {
120+
template <class> struct is_owning_view : std::false_type {};
121+
template <class R> struct is_owning_view<std::ranges::owning_view<R>> : std::true_type {};
122+
} // namespace detail
123+
template <class R>
124+
concept non_owning_view_c = std::ranges::view<R> && !detail::is_owning_view<std::remove_cvref_t<R>>::value;
125+
126+
// by ref adaptor to pass to functions which accepts std::ranges::view
127+
template <class R>
128+
concept owning_container_c = std::ranges::viewable_range<R> && !std::ranges::view<R> && !std::ranges::borrowed_range<R>;
129+
constexpr non_owning_view_c auto by_ref(owning_container_c auto& r) noexcept { return std::ranges::ref_view(r); }
130+
constexpr non_owning_view_c auto by_ref(owning_container_c auto const& r) noexcept { return std::ranges::ref_view(r); }
131+
constexpr non_owning_view_c auto by_const_ref(owning_container_c auto& r) noexcept { return by_ref(std::as_const(r)); }
132+
133+
// pgm functor concept
134+
// it should be cheap to copy, so it should be trivially copyable and small in size
135+
template <class T>
136+
concept functor_c = std::is_trivially_copyable_v<T> && (sizeof(T) <= 256);
137+
120138
// function to handle periodic mapping
121139
template <typename T> constexpr T map_to_cyclic_range(T value, T period) {
122140
static_assert(std::is_arithmetic_v<T>, "T must be an arithmetic type (integral or floating-point)");

power_grid_model_c/power_grid_model/include/power_grid_model/common/dummy_logging.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ class NoLogger : public Logger {
2020
void log(LogEvent /*tag*/, double /*value*/) override { /* no logging */ }
2121
void log(LogEvent /*tag*/, Idx /*value*/) override { /* no logging */ }
2222
void log(std::string_view /*message*/) const { /* no logging */ }
23-
template <LazyLoggingFn Fn> void log(LogEvent /*tag*/, Fn&& fn) const {
24-
capturing::into_the_void(std::forward<Fn>(fn));
25-
}
26-
template <LazyLoggingFn Fn> void log(Fn&& fn) const { capturing::into_the_void(std::forward<Fn>(fn)); }
23+
template <LazyLoggingFn Fn> void log(LogEvent /*tag*/, Fn /* fn */) const { /*do nothing*/ }
24+
template <LazyLoggingFn Fn> void log(Fn /* fn */) const { /*do nothing*/ }
2725
template <std::derived_from<Logger> T> T& merge_into(T& destination) const { return destination; }
2826
};
2927

power_grid_model_c/power_grid_model/include/power_grid_model/common/grouped_index_vector.hpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,29 @@ The input, i.e., [0, 1, 3] should be strictly increasing
3636
namespace power_grid_model {
3737

3838
namespace detail {
39-
template <std::ranges::viewable_range ElementGroups>
40-
constexpr auto sparse_encode(ElementGroups&& element_groups, Idx num_groups) {
39+
constexpr auto sparse_encode(non_owning_view_c auto element_groups, Idx num_groups) {
4140
IdxVector result(num_groups + 1);
42-
auto element_groups_view = std::views::all(std::forward<ElementGroups>(element_groups));
43-
auto next_group = std::begin(element_groups_view);
41+
auto next_group = std::begin(element_groups);
42+
auto const begin = std::begin(element_groups);
43+
auto const end = std::end(element_groups);
4444
for (auto const group : IdxRange{num_groups}) {
45-
next_group = std::upper_bound(next_group, std::end(element_groups_view), group);
46-
result[group + 1] = std::distance(std::begin(element_groups_view), next_group);
45+
next_group = std::upper_bound(next_group, end, group);
46+
result[group + 1] = std::distance(begin, next_group);
4747
}
4848
return result;
4949
}
50+
constexpr auto sparse_encode(IdxVector const& element_groups, Idx num_groups) {
51+
return sparse_encode(by_ref(element_groups), num_groups);
52+
}
5053

51-
template <std::ranges::viewable_range IndPtr> constexpr auto sparse_decode(IndPtr&& indptr) {
52-
auto indptr_view = std::views::all(std::forward<IndPtr>(indptr));
53-
auto result = IdxVector(indptr_view.back());
54-
for (Idx const group : IdxRange{static_cast<Idx>(indptr_view.size()) - 1}) {
55-
std::fill(std::begin(result) + indptr_view[group], std::begin(result) + indptr_view[group + 1], group);
54+
constexpr auto sparse_decode(non_owning_view_c auto indptr) {
55+
auto result = IdxVector(indptr.back());
56+
for (Idx const group : IdxRange{static_cast<Idx>(indptr.size()) - 1}) {
57+
std::fill(std::begin(result) + indptr[group], std::begin(result) + indptr[group + 1], group);
5658
}
5759
return result;
5860
}
61+
constexpr auto sparse_decode(IdxVector const& indptr) { return sparse_decode(by_ref(indptr)); }
5962

6063
template <typename T, typename ElementType>
6164
concept iterator_of = std::input_or_output_iterator<T> && requires(T const t) {

power_grid_model_c/power_grid_model/include/power_grid_model/common/iterator_facade.hpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ class IteratorFacade {
3535
public:
3636
using iterator_category = std::random_access_iterator_tag;
3737

38-
template <typename Self> constexpr decltype(auto) operator->(this Self&& self) {
39-
return &(*std::forward<Self>(self));
40-
}
38+
template <typename Self> constexpr decltype(auto) operator->(this Self const& self) { return &(*self); }
4139

4240
template <typename Self, typename Other>
4341
requires std::same_as<std::remove_cvref_t<Self>, std::remove_cvref_t<Other>>
@@ -83,23 +81,22 @@ class IteratorFacade {
8381
}
8482

8583
template <typename Self, std::integral Int>
86-
friend constexpr std::remove_cvref_t<Self> operator+(Self&& self, Int offset)
87-
requires std::derived_from<std::remove_cvref_t<Self>, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
84+
friend constexpr Self operator+(Self const& self, Int offset)
85+
requires std::derived_from<Self, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
8886
{
89-
using Result = std::remove_cvref_t<Self>;
90-
Result result{std::forward<Self>(self)};
87+
Self result{self};
9188
result += offset;
9289
return result;
9390
}
9491
template <typename Self, std::integral Int>
95-
requires std::derived_from<std::remove_cvref_t<Self>, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
96-
friend constexpr std::remove_cvref_t<Self> operator+(Int offset, Self&& self) {
97-
return std::forward<Self>(self) + offset;
92+
requires std::derived_from<Self, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
93+
friend constexpr Self operator+(Int offset, Self const& self) {
94+
return self + offset;
9895
}
9996
template <typename Self, std::integral Int>
100-
requires std::derived_from<std::remove_cvref_t<Self>, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
101-
friend constexpr std::remove_cvref_t<Self> operator-(Self&& self, Int idx) {
102-
return (std::forward<Self>(self)) + (-idx);
97+
requires std::derived_from<Self, IteratorFacade> //&& detail::iterator_facadeable_c<Self>
98+
friend constexpr Self operator-(Self const& self, Int idx) {
99+
return self + (-idx);
103100
}
104101

105102
template <typename Self>

power_grid_model_c/power_grid_model/include/power_grid_model/common/logging.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ enum class LogEvent : int16_t {
4646

4747
template <typename Fn>
4848
concept LazyLoggingFn = std::invocable<Fn> && std::convertible_to<std::invoke_result_t<Fn>, std::string> &&
49-
(!std::convertible_to<Fn, std::string_view>);
49+
(!std::convertible_to<Fn, std::string_view>) && functor_c<Fn>;
5050

5151
class Logger {
5252
public:
@@ -56,8 +56,8 @@ class Logger {
5656
virtual void log(LogEvent tag, Idx value) = 0;
5757

5858
void log(std::string_view message) { log(LogEvent::unknown, message); }
59-
template <LazyLoggingFn Fn> void log(LogEvent tag, Fn&& fn) { log(tag, std::invoke(std::forward<Fn>(fn))); }
60-
template <LazyLoggingFn Fn> void log(Fn&& fn) { log(LogEvent::unknown, std::invoke(std::forward<Fn>(fn))); }
59+
template <LazyLoggingFn Fn> void log(LogEvent tag, Fn fn) { log(tag, std::invoke(fn)); }
60+
template <LazyLoggingFn Fn> void log(Fn fn) { log(LogEvent::unknown, std::invoke(fn)); }
6161

6262
Logger(Logger&&) noexcept = default;
6363
Logger& operator=(Logger&&) noexcept = default;

power_grid_model_c/power_grid_model/include/power_grid_model/common/statistics.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ inline auto scale(DecomposedComplexRandVar<sym> const& var, ScaleType const& sca
314314
}
315315

316316
// combine multiple random variables of one quantity using Kalman filter
317-
template <std::ranges::view RandVarsView>
317+
template <non_owning_view_c RandVarsView>
318318
requires std::same_as<std::ranges::range_value_t<RandVarsView>,
319319
UniformRealRandVar<typename std::ranges::range_value_t<RandVarsView>::sym>> ||
320320
std::same_as<std::ranges::range_value_t<RandVarsView>,
@@ -345,7 +345,7 @@ constexpr auto combine(RandVarsView rand_vars) {
345345
.variance = VarianceType{1.0} / accumulated_inverse_variance};
346346
}
347347

348-
template <std::ranges::view RandVarsView>
348+
template <non_owning_view_c RandVarsView>
349349
requires std::same_as<std::ranges::range_value_t<RandVarsView>,
350350
DecomposedComplexRandVar<typename std::ranges::range_value_t<RandVarsView>::sym>>
351351
constexpr auto combine(RandVarsView rand_vars) {
@@ -373,7 +373,7 @@ template <symmetry_tag sym> inline RealValue<sym> cabs_or_real(ComplexValue<sym>
373373
}
374374
} // namespace detail
375375

376-
template <std::ranges::view RandVarsView>
376+
template <non_owning_view_c RandVarsView>
377377
requires std::same_as<std::ranges::range_value_t<RandVarsView>,
378378
UniformComplexRandVar<typename std::ranges::range_value_t<RandVarsView>::sym>>
379379
constexpr auto combine_magnitude(RandVarsView rand_vars) {

0 commit comments

Comments
 (0)