Skip to content

Commit c7a4bb3

Browse files
committed
move typed getters to Property & drop fallback interface
Better usability for user code if they deserialize individual Propertys. The fallback variants are not used internally and are redundant because there is a separate default behavior. Removed the msg parameter for Property exceptions. It was only used by a single edge-case which didn't really justify the use of the exception anyway. Instead allow `undefined` to be instantiated without parameters because the Property does not know its own name.
1 parent f351392 commit c7a4bb3

File tree

3 files changed

+56
-50
lines changed

3 files changed

+56
-50
lines changed

core/include/moveit/task_constructor/properties.h

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,40 @@ class Property
8181
Property();
8282

8383
/// base class for Property exceptions
84-
class error;
84+
class error : public std::runtime_error
85+
{
86+
protected:
87+
std::string property_name_;
88+
std::string msg_;
89+
90+
public:
91+
explicit error(const std::string& msg);
92+
const std::string& name() const { return property_name_; }
93+
void setName(const std::string& name);
94+
const char* what() const noexcept override { return msg_.c_str(); }
95+
};
96+
8597
/// exception thrown when accessing an undeclared property
86-
class undeclared;
98+
class undeclared : public Property::error
99+
{
100+
public:
101+
explicit undeclared(const std::string& name);
102+
};
103+
87104
/// exception thrown when accessing an undefined property
88-
class undefined;
105+
class undefined : public Property::error
106+
{
107+
public:
108+
explicit undefined();
109+
explicit undefined(const std::string& name);
110+
};
111+
89112
/// exception thrown when trying to set a value not matching the declared type
90-
class type_error;
113+
class type_error : public Property::error
114+
{
115+
public:
116+
explicit type_error(const std::string& current_type, const std::string& declared_type);
117+
};
91118

92119
using SourceFlags = uint;
93120
/// function callback used to initialize property value from another PropertyMap
@@ -101,12 +128,22 @@ class Property
101128
/// reset to default value (which can be empty)
102129
void reset();
103130

104-
/// the current value defined or will the fallback be used?
105-
inline bool defined() const { return !value_.empty(); }
131+
/// is a value defined?
132+
inline bool defined() const { return !(value_.empty() && default_.empty()); }
106133

107-
/// get current value (or default if not defined)
134+
/// get current value (or default if not set)
108135
inline const boost::any& value() const { return value_.empty() ? default_ : value_; }
109136
inline boost::any& value() { return value_.empty() ? default_ : value_; }
137+
138+
/// get typed value of property. Throws bad_any_cast on type mismatch, undefined if !defined().
139+
template <typename T>
140+
inline const T& value() const {
141+
const boost::any& v{ value() };
142+
if (v.empty())
143+
throw Property::undefined();
144+
return boost::any_cast<const T&>(value());
145+
}
146+
110147
/// get default value
111148
const boost::any& defaultValue() const { return default_; }
112149

@@ -142,34 +179,6 @@ class Property
142179
InitializerFunction initializer_;
143180
};
144181

145-
class Property::error : public std::runtime_error
146-
{
147-
protected:
148-
std::string property_name_;
149-
std::string msg_;
150-
151-
public:
152-
explicit error(const std::string& msg);
153-
const std::string& name() const { return property_name_; }
154-
void setName(const std::string& name);
155-
const char* what() const noexcept override { return msg_.c_str(); }
156-
};
157-
class Property::undeclared : public Property::error
158-
{
159-
public:
160-
explicit undeclared(const std::string& name, const std::string& msg = "undeclared");
161-
};
162-
class Property::undefined : public Property::error
163-
{
164-
public:
165-
explicit undefined(const std::string& name, const std::string& msg = "undefined");
166-
};
167-
class Property::type_error : public Property::error
168-
{
169-
public:
170-
explicit type_error(const std::string& current_type, const std::string& declared_type);
171-
};
172-
173182
// hasSerialize<T>::value provides a true/false constexpr depending on whether operator<< is supported.
174183
// This uses SFINAE, extracted from https://jguegant.github.io/blogs/tech/sfinae-introduction.html
175184
template <typename T, typename = std::ostream&>
@@ -318,19 +327,15 @@ class PropertyMap
318327
/// Get the value of a property. Throws undeclared if unknown name
319328
const boost::any& get(const std::string& name) const;
320329

321-
/// Get typed value of property. Throws undeclared, undefined, or bad_any_cast.
330+
/// Get typed value of property. Throws undeclared or bad_any_cast.
322331
template <typename T>
323332
const T& get(const std::string& name) const {
324-
const boost::any& value = get(name);
325-
if (value.empty())
326-
throw Property::undefined(name);
327-
return boost::any_cast<const T&>(value);
328-
}
329-
/// get typed value of property, using fallback if undefined. Throws bad_any_cast on type mismatch.
330-
template <typename T>
331-
const T& get(const std::string& name, const T& fallback) const {
332-
const boost::any& value = get(name);
333-
return (value.empty()) ? fallback : boost::any_cast<const T&>(value);
333+
try {
334+
return property(name).value<T>();
335+
} catch (Property::undefined& e) {
336+
e.setName(name);
337+
throw e;
338+
}
334339
}
335340

336341
/// count number of defined properties from given list

core/src/properties.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ void PropertyMap::set<boost::any>(const std::string& name, const boost::any& val
239239
auto range = props_.equal_range(name);
240240
if (range.first == range.second) { // name is not yet declared
241241
if (value.empty())
242-
throw Property::undeclared(name, "trying to set undeclared property '" + name + "' with NULL value");
242+
throw std::runtime_error("trying to set undeclared property '" + name + "' with NULL value");
243243
auto it = props_.insert(range.first, std::make_pair(name, Property(value.type(), "", boost::any())));
244244
it->second.setValue(value);
245245
} else
@@ -308,11 +308,13 @@ void Property::error::setName(const std::string& name) {
308308
msg_ = "Property '" + name + "': " + std::runtime_error::what();
309309
}
310310

311-
Property::undeclared::undeclared(const std::string& name, const std::string& msg) : Property::error(msg) {
311+
Property::undeclared::undeclared(const std::string& name) : Property::error("undeclared") {
312312
setName(name);
313313
}
314314

315-
Property::undefined::undefined(const std::string& name, const std::string& msg) : Property::error(msg) {
315+
Property::undefined::undefined() : Property::error("undefined") {}
316+
317+
Property::undefined::undefined(const std::string& name) : Property::undefined() {
316318
setName(name);
317319
}
318320

core/test/test_properties.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ TEST(Property, standard) {
1717

1818
EXPECT_THROW(props.get<double>("double4"), Property::undefined);
1919
EXPECT_FALSE(props.property("double4").defined());
20-
EXPECT_EQ(props.get<double>("double4", 0.0), 0.0);
2120

2221
props.set("double3", 3.0);
2322
EXPECT_EQ(props.get<double>("double3"), 3.0);

0 commit comments

Comments
 (0)