Skip to content

Commit 3a66da0

Browse files
committed
Add method to cast ValueHolder to specific Value.
1 parent 03e5d93 commit 3a66da0

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

nyan/concept.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@
44

55
#include <concepts>
66

7-
#include "nyan/value/value.h"
8-
97

108
namespace nyan {
119

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+
1219
/**
1320
* Type that is either a nyan value or object.
1421
* Object is not a value (ObjectValue is), but want to allow an
1522
* overloaded conversion for direct object access.
1623
*/
1724
template <typename T>
18-
concept ValueLike = std::derived_from<T, Value> || std::is_same_v<T, Object>;
25+
concept ValueOrObjectLike = std::is_same_v<T, Object> or ValueLike<T>;
1926

2027
} // namespace nyan

nyan/object.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class Object {
9696
*
9797
* @return Value of the member.
9898
*/
99-
template <ValueLike T>
99+
template <ValueOrObjectLike T>
100100
std::shared_ptr<T> get(const memberid_t &member, order_t t = LATEST_T) const;
101101

102102
/**
@@ -110,7 +110,7 @@ class Object {
110110
*
111111
* @return Value of the member.
112112
*/
113-
template <ValueLike T, bool may_be_none = true>
113+
template <ValueOrObjectLike T, bool may_be_none = true>
114114
std::optional<std::shared_ptr<T>> get_optional(const memberid_t &member, order_t t = LATEST_T) const;
115115

116116
/**
@@ -337,14 +337,14 @@ class Object {
337337
};
338338

339339

340-
template <ValueLike T>
340+
template <ValueOrObjectLike T>
341341
std::shared_ptr<T> Object::get(const memberid_t &member, order_t t) const {
342342
auto ret = this->get_optional<T, false>(member, t);
343343
return *ret;
344344
}
345345

346346

347-
template <ValueLike T, bool may_be_none>
347+
template <ValueOrObjectLike T, bool may_be_none>
348348
std::optional<std::shared_ptr<T>> Object::get_optional(const memberid_t &member, order_t t) const {
349349
std::shared_ptr<Value> value = this->get_value(member, t).get_ptr();
350350
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)