Skip to content

Commit a6d96bc

Browse files
authored
DPL: refactor ConfigParamRegistry to use C++20 (#13850)
Use constraints to make sure we can out-of-line known types of parameter. Remove the need to include Array2D.h when not used. Reduce dependence on ptree, in particular moving the helper methods out of line.
1 parent fff0296 commit a6d96bc

File tree

4 files changed

+214
-88
lines changed

4 files changed

+214
-88
lines changed

Framework/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ o2_add_library(Framework
5252
src/ConfigParamDiscovery.cxx
5353
src/ConfigParamStore.cxx
5454
src/ConfigParamsHelper.cxx
55+
src/ConfigParamRegistry.cxx
5556
src/ChannelParamSpec.cxx
5657
src/DDSConfigHelpers.cxx
5758
src/DataAllocator.cxx

Framework/Core/include/Framework/Array2D.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace o2::framework
2424
// has no range checks
2525
template <typename T>
2626
struct Array2D {
27+
void is_array_2d();
2728
using element_t = T;
2829

2930
Array2D()
@@ -161,6 +162,7 @@ template <typename T>
161162
class LabeledArray : public LabelMap
162163
{
163164
public:
165+
void is_labeled_array();
164166
using element_t = T;
165167

166168
LabeledArray()

Framework/Core/include/Framework/ConfigParamRegistry.h

Lines changed: 54 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,45 @@
1111
#ifndef O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
1212
#define O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
1313

14-
#include "Framework/ParamRetriever.h"
1514
#include "Framework/ConfigParamStore.h"
15+
#include <boost/property_tree/ptree.hpp>
1616
#include "Framework/Traits.h"
17-
#include "Framework/VariantPropertyTreeHelpers.h"
1817

19-
#include <boost/property_tree/ptree_fwd.hpp>
18+
#include <concepts>
19+
#include <cstdint>
2020
#include <memory>
2121
#include <string>
2222
#include <cassert>
23+
#include <type_traits>
2324

24-
namespace
25-
{
2625
template <typename T>
27-
constexpr auto isSimpleType()
28-
{
29-
return std::is_same_v<T, int> ||
30-
std::is_same_v<T, int8_t> ||
31-
std::is_same_v<T, int16_t> ||
32-
std::is_same_v<T, uint8_t> ||
33-
std::is_same_v<T, uint16_t> ||
34-
std::is_same_v<T, uint32_t> ||
35-
std::is_same_v<T, uint64_t> ||
36-
std::is_same_v<T, int64_t> ||
37-
std::is_same_v<T, long> ||
38-
std::is_same_v<T, float> ||
39-
std::is_same_v<T, double> ||
40-
std::is_same_v<T, bool>;
41-
}
42-
} // namespace
26+
concept SimpleConfigValueType = std::same_as<T, int> ||
27+
std::same_as<T, int8_t> ||
28+
std::same_as<T, int16_t> ||
29+
std::same_as<T, uint8_t> ||
30+
std::same_as<T, uint16_t> ||
31+
std::same_as<T, uint32_t> ||
32+
std::same_as<T, uint64_t> ||
33+
std::same_as<T, long> ||
34+
std::same_as<T, long long> ||
35+
std::same_as<T, float> ||
36+
std::same_as<T, double> ||
37+
std::same_as<T, bool>;
38+
39+
template <typename T>
40+
concept StringConfigValueType = std::same_as<T, std::string>;
41+
42+
template <typename T>
43+
concept PtreeConfigValueType = std::same_as<T, boost::property_tree::ptree> || std::constructible_from<T, boost::property_tree::ptree>;
44+
45+
template <typename T>
46+
concept Array2DLike = requires(T& t) { t.is_array_2d(); };
47+
48+
template <typename T>
49+
concept LabeledArrayLike = requires(T& t) { t.is_labeled_array(); };
50+
51+
template <typename T>
52+
concept ConfigValueType = SimpleConfigValueType<T> || StringConfigValueType<T> || o2::framework::base_of_template<std::vector, T> || Array2DLike<T> || LabeledArrayLike<T>;
4353

4454
namespace o2::framework
4555
{
@@ -54,87 +64,43 @@ class ConfigParamStore;
5464
class ConfigParamRegistry
5565
{
5666
public:
57-
ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store)
58-
: mStore{std::move(store)}
59-
{
60-
}
67+
ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store);
6168

62-
bool isSet(const char* key) const
63-
{
64-
return mStore->store().count(key);
65-
}
69+
bool isSet(const char* key) const;
6670

67-
bool hasOption(const char* key) const
68-
{
69-
return mStore->store().get_child_optional(key).is_initialized();
70-
}
71+
bool hasOption(const char* key) const;
7172

72-
bool isDefault(const char* key) const
73-
{
74-
return mStore->store().count(key) > 0 && mStore->provenance(key) != "default";
75-
}
73+
bool isDefault(const char* key) const;
7674

77-
[[nodiscard]] std::vector<ConfigParamSpec> const& specs() const
78-
{
79-
return mStore->specs();
80-
}
75+
[[nodiscard]] std::vector<ConfigParamSpec> const& specs() const;
8176

82-
template <typename T>
83-
T get(const char* key) const
84-
{
85-
assert(mStore.get());
86-
try {
87-
if constexpr (isSimpleType<T>()) {
88-
return mStore->store().get<T>(key);
89-
} else if constexpr (std::is_same_v<T, std::string>) {
90-
return mStore->store().get<std::string>(key);
91-
} else if constexpr (std::is_same_v<T, std::string_view>) {
92-
return std::string_view{mStore->store().get<std::string>(key)};
93-
} else if constexpr (base_of_template<std::vector, T>) {
94-
return vectorFromBranch<typename T::value_type>(mStore->store().get_child(key));
95-
} else if constexpr (base_of_template<o2::framework::Array2D, T>) {
96-
return array2DFromBranch<typename T::element_t>(mStore->store().get_child(key));
97-
} else if constexpr (base_of_template<o2::framework::LabeledArray, T>) {
98-
return labeledArrayFromBranch<typename T::element_t>(mStore->store().get_child(key));
99-
} else if constexpr (std::is_same_v<T, boost::property_tree::ptree>) {
100-
return mStore->store().get_child(key);
101-
} else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree>) {
102-
return T{mStore->store().get_child(key)};
103-
} else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree> == false) {
104-
static_assert(std::is_constructible_v<T, boost::property_tree::ptree> == false,
105-
"Not a basic type and no constructor from ptree provided");
106-
}
107-
} catch (std::exception& e) {
108-
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
109-
} catch (...) {
110-
throw std::invalid_argument(std::string("error parsing option: ") + key);
111-
}
112-
throw std::invalid_argument(std::string("bad type for option: ") + key);
113-
}
77+
template <ConfigValueType T>
78+
T get(const char* key) const;
11479

11580
template <typename T>
116-
void override(const char* key, const T& val) const
117-
{
118-
assert(mStore.get());
119-
try {
120-
mStore->store().put(key, val);
121-
} catch (std::exception& e) {
122-
throw std::invalid_argument(std::string("failed to store an option: ") + key + " (" + e.what() + ")");
123-
} catch (...) {
124-
throw std::invalid_argument(std::string("failed to store an option: ") + key);
125-
}
126-
}
81+
T get(const char* key) const;
82+
83+
void override(const char* key, ConfigValueType auto const& val) const;
12784

12885
// Load extra parameters discovered while we process data
129-
void loadExtra(std::vector<ConfigParamSpec>& extras)
130-
{
131-
mStore->load(extras);
132-
}
86+
void loadExtra(std::vector<ConfigParamSpec>& extras);
13387

13488
private:
13589
std::unique_ptr<ConfigParamStore> mStore;
13690
};
13791

92+
template <typename T>
93+
T ConfigParamRegistry::get(const char* key) const
94+
{
95+
try {
96+
return T{mStore->store().get_child(key)};
97+
} catch (std::exception& e) {
98+
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
99+
} catch (...) {
100+
throw std::invalid_argument(std::string("error parsing option: ") + key);
101+
}
102+
}
103+
138104
} // namespace o2::framework
139105

140106
#endif // O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
#include "Framework/ConfigParamRegistry.h"
12+
#include "Framework/VariantPropertyTreeHelpers.h"
13+
#include "Framework/Array2D.h"
14+
15+
namespace o2::framework
16+
{
17+
18+
ConfigParamRegistry::ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store)
19+
: mStore{std::move(store)}
20+
{
21+
}
22+
23+
bool ConfigParamRegistry::isSet(const char* key) const
24+
{
25+
return mStore->store().count(key);
26+
}
27+
28+
bool ConfigParamRegistry::hasOption(const char* key) const
29+
{
30+
return mStore->store().get_child_optional(key).is_initialized();
31+
}
32+
33+
bool ConfigParamRegistry::isDefault(const char* key) const
34+
{
35+
return mStore->store().count(key) > 0 && mStore->provenance(key) != "default";
36+
}
37+
38+
namespace
39+
{
40+
template <SimpleConfigValueType T>
41+
T getImpl(boost::property_tree::ptree const& tree, const char* key)
42+
{
43+
return tree.get<T>(key);
44+
}
45+
46+
template <StringConfigValueType T>
47+
T getImpl(boost::property_tree::ptree const& tree, const char* key)
48+
{
49+
return tree.get<std::string>(key);
50+
}
51+
52+
template <typename T>
53+
requires base_of_template<std::vector, T>
54+
auto getImpl(boost::property_tree::ptree const& tree, const char* key)
55+
{
56+
return o2::framework::vectorFromBranch<typename T::value_type>(tree.get_child(key));
57+
}
58+
59+
template <Array2DLike T>
60+
auto getImpl(boost::property_tree::ptree& tree, const char* key)
61+
{
62+
return array2DFromBranch<typename T::element_t>(tree.get_child(key));
63+
}
64+
65+
template <LabeledArrayLike T>
66+
auto getImpl(boost::property_tree::ptree& tree, const char* key)
67+
{
68+
return labeledArrayFromBranch<typename T::element_t>(tree.get_child(key));
69+
}
70+
} // namespace
71+
72+
template <ConfigValueType T>
73+
T ConfigParamRegistry::get(const char* key) const
74+
{
75+
try {
76+
return getImpl<T>(this->mStore->store(), key);
77+
} catch (std::exception& e) {
78+
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
79+
} catch (...) {
80+
throw std::invalid_argument(std::string("error parsing option: ") + key);
81+
}
82+
}
83+
84+
void ConfigParamRegistry::override(const char* key, ConfigValueType auto const& val) const
85+
{
86+
try {
87+
mStore->store().put(key, val);
88+
} catch (std::exception& e) {
89+
throw std::invalid_argument(std::string("failed to store an option: ") + key + " (" + e.what() + ")");
90+
} catch (...) {
91+
throw std::invalid_argument(std::string("failed to store an option: ") + key);
92+
}
93+
}
94+
95+
// Load extra parameters discovered while we process data
96+
void ConfigParamRegistry::loadExtra(std::vector<ConfigParamSpec>& extras)
97+
{
98+
mStore->load(extras);
99+
}
100+
101+
[[nodiscard]] std::vector<ConfigParamSpec> const& ConfigParamRegistry::specs() const
102+
{
103+
return mStore->specs();
104+
}
105+
106+
template int8_t ConfigParamRegistry::get<int8_t>(const char* key) const;
107+
template short ConfigParamRegistry::get<short>(const char* key) const;
108+
template int ConfigParamRegistry::get<int>(const char* key) const;
109+
template long ConfigParamRegistry::get<long>(const char* key) const;
110+
template long long ConfigParamRegistry::get<long long>(const char* key) const;
111+
template uint8_t ConfigParamRegistry::get<uint8_t>(const char* key) const;
112+
template uint16_t ConfigParamRegistry::get<uint16_t>(const char* key) const;
113+
template uint32_t ConfigParamRegistry::get<uint32_t>(const char* key) const;
114+
template uint64_t ConfigParamRegistry::get<uint64_t>(const char* key) const;
115+
template LabeledArray<std::string> ConfigParamRegistry::get<LabeledArray<std::string>>(const char* key) const;
116+
template LabeledArray<double> ConfigParamRegistry::get<LabeledArray<double>>(const char* key) const;
117+
template LabeledArray<float> ConfigParamRegistry::get<LabeledArray<float>>(const char* key) const;
118+
template LabeledArray<int> ConfigParamRegistry::get<LabeledArray<int>>(const char* key) const;
119+
template Array2D<std::string> ConfigParamRegistry::get<Array2D<std::string>>(const char* key) const;
120+
template Array2D<double> ConfigParamRegistry::get<Array2D<double>>(const char* key) const;
121+
template Array2D<float> ConfigParamRegistry::get<Array2D<float>>(const char* key) const;
122+
template Array2D<int> ConfigParamRegistry::get<Array2D<int>>(const char* key) const;
123+
template std::vector<std::string> ConfigParamRegistry::get<std::vector<std::string>>(const char* key) const;
124+
template std::vector<double> ConfigParamRegistry::get<std::vector<double>>(const char* key) const;
125+
template std::vector<float> ConfigParamRegistry::get<std::vector<float>>(const char* key) const;
126+
template std::vector<int> ConfigParamRegistry::get<std::vector<int>>(const char* key) const;
127+
template float ConfigParamRegistry::get<float>(const char* key) const;
128+
template double ConfigParamRegistry::get<double>(const char* key) const;
129+
template std::string ConfigParamRegistry::get<std::string>(const char* key) const;
130+
template bool ConfigParamRegistry::get<bool>(const char* key) const;
131+
132+
template void ConfigParamRegistry::override(const char* key, int8_t const&) const;
133+
template void ConfigParamRegistry::override(const char* key, int16_t const&) const;
134+
template void ConfigParamRegistry::override(const char* key, int32_t const&) const;
135+
template void ConfigParamRegistry::override(const char* key, int64_t const&) const;
136+
template void ConfigParamRegistry::override(const char* key, uint8_t const&) const;
137+
template void ConfigParamRegistry::override(const char* key, uint16_t const&) const;
138+
template void ConfigParamRegistry::override(const char* key, uint32_t const&) const;
139+
template void ConfigParamRegistry::override(const char* key, uint64_t const&) const;
140+
template void ConfigParamRegistry::override(const char* key, float const&) const;
141+
template void ConfigParamRegistry::override(const char* key, double const&) const;
142+
template void ConfigParamRegistry::override(const char* key, std::string const&) const;
143+
template void ConfigParamRegistry::override(const char* key, bool const&) const;
144+
145+
//template void ConfigParamRegistry::override(char const* key, LabeledArray<std::string> const&) const;
146+
//template void ConfigParamRegistry::override(char const* key, LabeledArray<double> const&) const;
147+
//template void ConfigParamRegistry::override(char const* key, LabeledArray<float> const&) const;
148+
//template void ConfigParamRegistry::override(char const* key, LabeledArray<int> const&) const;
149+
//template void ConfigParamRegistry::override(char const* key, Array2D<std::string> const&) const;
150+
//template void ConfigParamRegistry::override(char const* key, Array2D<double> const&) const;
151+
//template void ConfigParamRegistry::override(char const* key, Array2D<float> const&) const;
152+
//template void ConfigParamRegistry::override(char const* key, Array2D<int> const&) const;
153+
//template void ConfigParamRegistry::override(char const* key, std::vector<std::string> const&) const;
154+
//template void ConfigParamRegistry::override(char const* key, std::vector<double> const&) const;
155+
//template void ConfigParamRegistry::override(char const* key, std::vector<float> const&) const;
156+
//template void ConfigParamRegistry::override(char const* key, std::vector<int> const&) const;
157+
} // namespace o2::framework

0 commit comments

Comments
 (0)