Skip to content

Commit a79a44f

Browse files
authored
Merge pull request #125 from heinezen/feature/parent_check
Handle casting from `ValueHolder` to specific `Value` directly in nyan API
2 parents 12f2735 + 3a66da0 commit a79a44f

File tree

6 files changed

+101
-25
lines changed

6 files changed

+101
-25
lines changed

nyan/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_library(nyan SHARED
3030
basic_type.cpp
3131
c3.cpp
3232
change_tracker.cpp
33+
concept.cpp
3334
config.cpp
3435
curve.cpp
3536
database.cpp

nyan/concept.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2025-2025 the nyan authors, LGPLv3+. See copying.md for legal info.
2+
3+
#include "concept.h"
4+
5+
6+
namespace nyan {
7+
8+
// this file is intentionally empty
9+
10+
}

nyan/concept.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2025-2025 the nyan authors, LGPLv3+. See copying.md for legal info.
2+
3+
#pragma once
4+
5+
#include <concepts>
6+
7+
8+
namespace nyan {
9+
10+
class Value;
11+
class Object;
12+
13+
/**
14+
* Type that is a nyan value.
15+
*/
16+
template <typename T>
17+
concept ValueLike = std::derived_from<T, Value>;
18+
19+
/**
20+
* Type that is either a nyan value or object.
21+
* Object is not a value (ObjectValue is), but want to allow an
22+
* overloaded conversion for direct object access.
23+
*/
24+
template <typename T>
25+
concept ValueOrObjectLike = std::is_same_v<T, Object> or ValueLike<T>;
26+
27+
} // namespace nyan

nyan/object.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2016-2024 the nyan authors, LGPLv3+. See copying.md for legal info.
1+
// Copyright 2016-2025 the nyan authors, LGPLv3+. See copying.md for legal info.
22

33
#include "object.h"
44

@@ -192,6 +192,10 @@ const std::deque<fqon_t> &Object::get_parents(order_t t) const {
192192

193193

194194
bool Object::has(const memberid_t &member, order_t t) const {
195+
return this->has_member(member, t);
196+
}
197+
198+
bool Object::has_member(const memberid_t &member, order_t t) const {
195199
// TODO: cache?
196200

197201
const std::vector<fqon_t> &lin = this->get_linearized(t);
@@ -206,7 +210,7 @@ bool Object::has(const memberid_t &member, order_t t) const {
206210
}
207211

208212

209-
bool Object::extends(fqon_t other_fqon, order_t t) const {
213+
bool Object::extends(const fqon_t &other_fqon, order_t t) const {
210214
if (this->name == other_fqon) {
211215
return true;
212216
}

nyan/object.h

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info.
1+
// Copyright 2016-2025 the nyan authors, LGPLv3+. See copying.md for legal info.
22
#pragma once
33

44

5-
#include <concepts>
65
#include <deque>
76
#include <memory>
87
#include <sstream>
@@ -11,6 +10,7 @@
1110
#include <vector>
1211

1312
#include "api_error.h"
13+
#include "concept.h"
1414
#include "config.h"
1515
#include "object_notifier_types.h"
1616
#include "util.h"
@@ -31,15 +31,6 @@ class Value;
3131
class View;
3232

3333

34-
/**
35-
* Type that is either a nyan value or object.
36-
* Object is not a value (ObjectValue is), but want to allow an
37-
* overloaded conversion for direct object access.
38-
*/
39-
template <typename T>
40-
concept ValueLike = std::derived_from<T, Value> || std::is_same_v<T, Object>;
41-
42-
4334
/**
4435
* Handle for accessing a nyan object independent of time.
4536
*/
@@ -105,7 +96,7 @@ class Object {
10596
*
10697
* @return Value of the member.
10798
*/
108-
template <ValueLike T>
99+
template <ValueOrObjectLike T>
109100
std::shared_ptr<T> get(const memberid_t &member, order_t t = LATEST_T) const;
110101

111102
/**
@@ -119,7 +110,7 @@ class Object {
119110
*
120111
* @return Value of the member.
121112
*/
122-
template <ValueLike T, bool may_be_none = true>
113+
template <ValueOrObjectLike T, bool may_be_none = true>
123114
std::optional<std::shared_ptr<T>> get_optional(const memberid_t &member, order_t t = LATEST_T) const;
124115

125116
/**
@@ -245,19 +236,30 @@ class Object {
245236
*
246237
* @return true if the member exists for this object, else false.
247238
*/
239+
[[deprecated("Use has_member(..) instead")]]
248240
bool has(const memberid_t &member, order_t t = LATEST_T) const;
249241

250242
/**
251-
* Check if this object is a child of the given parent at a given time.
243+
* Check if this object has a member with a given name at a given time.
244+
*
245+
* @param member Identifier of the member.
246+
* @param t Time for which the member existence is checked.
247+
*
248+
* @return true if the member exists for this object, else false.
249+
*/
250+
bool has_member(const memberid_t &member, order_t t = LATEST_T) const;
251+
252+
/**
253+
* Check if this object is a descendant/child of the given object at a given time.
252254
*
253-
* @param other_fqon Identifier of the suspected parent object.
255+
* @param other_fqon Identifier of the suspected parent/ancestor object.
254256
* @param t Time for which the relationship is checked.
255257
*
256-
* @return true if the parent's identifier equals this object's
257-
* identifier or that of any of its (transitive) parents,
258-
* else false
258+
* @return true if the ancestors's identifier equals this object's
259+
* identifier or that of any of its (transitive) parents,
260+
* else false
259261
*/
260-
bool extends(fqon_t other_fqon, order_t t = LATEST_T) const;
262+
bool extends(const fqon_t &other_fqon, order_t t = LATEST_T) const;
261263

262264
/**
263265
* Get the metadata information object for this object.
@@ -335,14 +337,14 @@ class Object {
335337
};
336338

337339

338-
template <ValueLike T>
340+
template <ValueOrObjectLike T>
339341
std::shared_ptr<T> Object::get(const memberid_t &member, order_t t) const {
340342
auto ret = this->get_optional<T, false>(member, t);
341343
return *ret;
342344
}
343345

344346

345-
template <ValueLike T, bool may_be_none>
347+
template <ValueOrObjectLike T, bool may_be_none>
346348
std::optional<std::shared_ptr<T>> Object::get_optional(const memberid_t &member, order_t t) const {
347349
std::shared_ptr<Value> value = this->get_value(member, t).get_ptr();
348350
if constexpr (may_be_none) {

nyan/value/value_holder.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
1+
// Copyright 2017-2025 the nyan authors, LGPLv3+. See copying.md for legal info.
22
#pragma once
33

44
#include <memory>
55

6+
#include "../api_error.h"
7+
#include "../concept.h"
8+
#include "../util.h"
9+
610

711
namespace nyan {
812

@@ -26,12 +30,26 @@ class ValueHolder {
2630
ValueHolder &operator=(const std::shared_ptr<Value> &value);
2731

2832
/**
29-
* Get the shared pointer of this ValueHolder.
33+
* Get the shared pointer to the value wrapped by this holder.
3034
*
3135
* @return Shared pointer to this holder's value.
3236
*/
3337
const std::shared_ptr<Value> &get_ptr() const;
3438

39+
/**
40+
* Get a shared pointer to the value stored by this holder.
41+
*
42+
* Auto-converts the value to type T, which must be a nyan::Value type.
43+
*
44+
* @tparam T Type of the value to retrieve.
45+
*
46+
* @return Value stored by this holder.
47+
*
48+
* @throws InternalError if the value is not of type T.
49+
*/
50+
template <ValueLike T>
51+
const std::shared_ptr<T> get_value_ptr() const;
52+
3553
/**
3654
* Check if this holder points to a value.
3755
*
@@ -74,6 +92,20 @@ class ValueHolder {
7492
std::shared_ptr<Value> value;
7593
};
7694

95+
96+
template <ValueLike T>
97+
const std::shared_ptr<T> ValueHolder::get_value_ptr() const {
98+
auto ret = std::dynamic_pointer_cast<T>(this->value);
99+
100+
if (not ret) {
101+
throw APIError{"ValueHolder does not contain a value of type "
102+
+ util::typestring<T>() + ", but got "
103+
+ util::typestring(this->value.get())};
104+
}
105+
106+
return ret;
107+
}
108+
77109
} // namespace nyan
78110

79111

0 commit comments

Comments
 (0)