Skip to content

Commit e435b99

Browse files
allow virtual configs to be templated to set optional value before constructing (#37)
1 parent 83595cb commit e435b99

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

config_utilities/include/config_utilities/virtual_config.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ namespace config {
5050
* class.
5151
*
5252
* @tparam BaseT The base class of the object that should be created from the config.
53+
* @tparam BaseT Whether or not the virtual config is optional when constructed (useful for maps and vectors of configs)
5354
*/
54-
template <class BaseT>
55+
template <class BaseT, bool OptionalByDefault = false>
5556
class VirtualConfig {
5657
public:
5758
VirtualConfig() = default;
@@ -184,25 +185,25 @@ class VirtualConfig {
184185
}
185186

186187
private:
187-
template <typename T>
188-
friend void declare_config(VirtualConfig<T>&);
188+
template <typename T, bool Opt>
189+
friend void declare_config(VirtualConfig<T, Opt>&);
189190
friend struct internal::Visitor;
190191

191-
bool optional_ = false;
192+
bool optional_ = OptionalByDefault;
192193
std::unique_ptr<internal::ConfigWrapper> config_;
193194
};
194195

195196
namespace internal {
196197

197198
// Declare virtual config types.
198-
template <typename T>
199-
struct is_virtual_config<VirtualConfig<T>> : std::true_type {};
199+
template <typename T, bool Opt>
200+
struct is_virtual_config<VirtualConfig<T, Opt>> : std::true_type {};
200201

201202
} // namespace internal
202203

203204
// Declare the Virtual Config a config, so it can be handled like any other object.
204-
template <typename BaseT>
205-
void declare_config(VirtualConfig<BaseT>& config) {
205+
template <typename BaseT, bool Opt>
206+
void declare_config(VirtualConfig<BaseT, Opt>& config) {
206207
auto data = internal::Visitor::visitVirtualConfig(config.isSet(), config.optional_, config.getType());
207208

208209
// underlying derived type is not required if the config is optional, or if the config has been

config_utilities/test/tests/virtual_config.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,27 @@ void declare_config(ObjectWithBase::Config& config) {
117117
config::field(config.base_config, "base_config", false);
118118
}
119119

120+
struct ObjectWithOptionalConfigs {
121+
struct Config {
122+
std::vector<VirtualConfig<Base2, true>> modules;
123+
} const config;
124+
125+
explicit ObjectWithOptionalConfigs(const Config& config) : config(config::checkValid(config)) {
126+
for (const auto& base_config : config.modules) {
127+
if (base_config) {
128+
valid.emplace_back(base_config.create());
129+
}
130+
}
131+
}
132+
133+
std::vector<std::unique_ptr<Base2>> valid;
134+
};
135+
136+
void declare_config(ObjectWithOptionalConfigs::Config& config) {
137+
config::name("ObjectWithOptionalConfigs");
138+
config::field(config.modules, "modules");
139+
}
140+
120141
TEST(VirtualConfig, isSet) {
121142
Settings().restoreDefaults();
122143

@@ -348,4 +369,19 @@ TEST(VirtualConfig, getUnderlying) {
348369
EXPECT_TRUE(config.getUnderlying<Derived2A::Config>());
349370
}
350371

372+
TEST(VirtualConfig, optionalByDefault) {
373+
Settings().restoreDefaults();
374+
375+
const std::string yaml_str = R"""(modules:
376+
- {type: testing}
377+
- {a: 5, b: 6}
378+
- {type: Derived2}
379+
)""";
380+
381+
const auto node = YAML::Load(yaml_str);
382+
const auto config = config::fromYaml<ObjectWithOptionalConfigs::Config>(node);
383+
const ObjectWithOptionalConfigs object(config);
384+
EXPECT_EQ(object.valid.size(), 1u);
385+
}
386+
351387
} // namespace config::test

0 commit comments

Comments
 (0)