registry: standalone context type (close #575)
This commit is contained in:
@@ -911,40 +911,39 @@ use the preferred tool.
|
||||
|
||||
## Context variables
|
||||
|
||||
It is often convenient to assign context variables to a registry, so as to make
|
||||
it the only _source of truth_ of an application.<br/>
|
||||
This is possible by means of a member function named `set` to use to create a
|
||||
context variable from a given type. Either `ctx` or `try_ctx` can be used to
|
||||
retrieve the newly created instance, while `unset` is meant to clear the
|
||||
variable if needed:
|
||||
Each registry has a _context_ associated with it, which is an `any` object map
|
||||
accessible by type for convenience.<br/>
|
||||
The context is returned via the `ctx` functions and offers a minimal set of
|
||||
features including the following:
|
||||
|
||||
```cpp
|
||||
// creates a new context variable initialized with the given values
|
||||
registry.set<my_type>(42, 'c');
|
||||
registry.ctx().emplace<my_type>(42, 'c');
|
||||
|
||||
// gets the context variable as a non-const reference from a non-const registry
|
||||
auto &var = registry.ctx<my_type>();
|
||||
auto &var = registry.ctx().at<my_type>();
|
||||
|
||||
// gets the context variable as a const reference from either a const or a non-const registry
|
||||
const auto &cvar = registry.ctx<const my_type>();
|
||||
const auto &cvar = registry.ctx().at<const my_type>();
|
||||
|
||||
// unsets the context variable
|
||||
registry.unset<my_type>();
|
||||
registry.ctx().erase<my_type>();
|
||||
```
|
||||
|
||||
The type of a context variable must be such that it's default constructible and
|
||||
can be moved. The `set` member function either creates a new instance of the
|
||||
context variable or overwrites an already existing one if any.<br/>
|
||||
The `try_ctx` member function returns a pointer to the context variable if it
|
||||
exists, otherwise it returns a null pointer. As `ctx`, it supports both const
|
||||
and non-const types and requires a const one when used on a const registry:
|
||||
can be moved.<br/>
|
||||
For all users who want to use the context but don't want to create elements, the
|
||||
`contains` and `find` functions are also available:
|
||||
|
||||
```cpp
|
||||
if(auto *cptr = registry.try_ctx<const my_type>(); cptr) {
|
||||
// uses the context variable associated with the registry, if any
|
||||
}
|
||||
const bool contains = registry.ctx().contains<my_type>();
|
||||
const my_type *value = registry.ctx().find<const my_type>();
|
||||
```
|
||||
|
||||
Both support constant types, as does `at`. Furthermore, since the context is
|
||||
essentially a map of `any`s, it offers full support for references and allows
|
||||
users to hook externally managed objects to the registry itself.
|
||||
|
||||
### Aliased properties
|
||||
|
||||
Context variables can also be used to create aliases for existing variables that
|
||||
@@ -955,13 +954,13 @@ lvalue is necessarily provided as an argument:
|
||||
|
||||
```cpp
|
||||
time clock;
|
||||
registry.set<my_type &>(clock);
|
||||
registry.ctx().emplace<my_type &>(clock);
|
||||
```
|
||||
|
||||
Read-only aliased properties are created using const types instead:
|
||||
|
||||
```cpp
|
||||
registry.set<const my_type &>(clock);
|
||||
registry.ctx().emplace<const my_type &>(clock);
|
||||
```
|
||||
|
||||
From the point of view of the user, there are no differences between a variable
|
||||
@@ -970,12 +969,11 @@ variables aren't accesible as non-const references:
|
||||
|
||||
```cpp
|
||||
// read-only variables only support const access
|
||||
const my_type *ptr = registry.try_ctx<const my_type>();
|
||||
const my_type &var = registry.ctx<const my_type>();
|
||||
const my_type *ptr = registry.ctx().find<const my_type>();
|
||||
const my_type &var = registry.ctx().at<const my_type>();
|
||||
```
|
||||
|
||||
Aliased properties can be unset and are overwritten when `set` is invoked, as it
|
||||
happens with standard variables.
|
||||
Aliased properties can also be erased as it happens with any other variable.
|
||||
|
||||
## Pointer stability
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ class basic_organizer final {
|
||||
} else if constexpr(internal::is_view_v<Type>) {
|
||||
return as_view{reg};
|
||||
} else {
|
||||
return reg.template ctx_or_set<std::remove_reference_t<Type>>();
|
||||
return reg.ctx().template emplace<std::remove_reference_t<Type>>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,54 @@ template<typename ILhs, typename IRhs>
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
class registry_context {
|
||||
template<typename Type>
|
||||
[[nodiscard]] id_type type_to_key() const ENTT_NOEXCEPT {
|
||||
return type_id<std::remove_const_t<std::remove_reference_t<Type>>>().hash();
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename Type, typename... Args>
|
||||
Type &emplace(Args &&...args) {
|
||||
return any_cast<Type &>(data.try_emplace(type_to_key<Type>(), std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void erase() {
|
||||
data.erase(type_to_key<Type>());
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] std::add_const_t<Type> &at() const {
|
||||
return any_cast<std::add_const_t<Type> &>(data.at(type_to_key<Type>()));
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] Type &at() {
|
||||
return any_cast<Type &>(data.at(type_to_key<Type>()));
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] std::add_const_t<Type> *find() const {
|
||||
auto it = data.find(type_to_key<Type>());
|
||||
return it == data.cend() ? nullptr : any_cast<std::add_const_t<Type>>(&it->second);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] Type *find() {
|
||||
auto it = data.find(type_to_key<Type>());
|
||||
return it == data.end() ? nullptr : any_cast<Type>(&it->second);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] bool contains() const {
|
||||
return data.contains(type_to_key<Type>());
|
||||
}
|
||||
|
||||
private:
|
||||
dense_hash_map<id_type, basic_any<0u>, identity> data;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
@@ -281,6 +329,8 @@ public:
|
||||
using size_type = std::size_t;
|
||||
/*! @brief Common type among all storage types. */
|
||||
using base_type = basic_common_type;
|
||||
/*! @brief Context type. */
|
||||
using context = internal::registry_context;
|
||||
|
||||
/*! @brief Default constructor. */
|
||||
basic_registry() = default;
|
||||
@@ -291,10 +341,10 @@ public:
|
||||
*/
|
||||
basic_registry(basic_registry &&other) ENTT_NOEXCEPT
|
||||
: pools{std::move(other.pools)},
|
||||
vars{std::move(other.vars)},
|
||||
groups{std::move(other.groups)},
|
||||
entities{std::move(other.entities)},
|
||||
free_list{other.free_list} {
|
||||
free_list{other.free_list},
|
||||
vars{std::move(other.vars)} {
|
||||
for(auto &&curr: pools) {
|
||||
curr.second->bind(forward_as_any(*this));
|
||||
}
|
||||
@@ -307,10 +357,10 @@ public:
|
||||
*/
|
||||
basic_registry &operator=(basic_registry &&other) ENTT_NOEXCEPT {
|
||||
pools = std::move(other.pools);
|
||||
vars = std::move(other.vars);
|
||||
groups = std::move(other.groups);
|
||||
entities = std::move(other.entities);
|
||||
free_list = other.free_list;
|
||||
vars = std::move(other.vars);
|
||||
|
||||
for(auto &&curr: pools) {
|
||||
curr.second->bind(forward_as_any(*this));
|
||||
@@ -1409,118 +1459,24 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Binds an object to the context of the registry.
|
||||
*
|
||||
* If the value already exists it is overwritten, otherwise a new instance
|
||||
* of the given type is created and initialized with the arguments provided.
|
||||
*
|
||||
* @tparam Type Type of object to set.
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @param args Parameters to use to initialize the value.
|
||||
* @return A reference to the newly created object.
|
||||
* @brief Returns the context object, that is, a general purpose container.
|
||||
* @return The context object, that is, a general purpose container.
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
Type &set(Args &&...args) {
|
||||
auto &&elem = vars[type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()];
|
||||
elem.template emplace<Type>(std::forward<Args>(args)...);
|
||||
return any_cast<Type &>(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unsets a context variable if it exists.
|
||||
* @tparam Type Type of object to set.
|
||||
*/
|
||||
template<typename Type>
|
||||
void unset() {
|
||||
vars.erase(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Binds an object to the context of the registry.
|
||||
*
|
||||
* In case the context doesn't contain the given object, the parameters
|
||||
* provided are used to construct it.
|
||||
*
|
||||
* @tparam Type Type of object to set.
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @param args Parameters to use to initialize the object.
|
||||
* @return A reference to the object in the context of the registry.
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
[[nodiscard]] Type &ctx_or_set(Args &&...args) {
|
||||
return any_cast<Type &>(vars.try_emplace(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value(), std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to an object in the context of the registry.
|
||||
* @tparam Type Type of object to get.
|
||||
* @return A pointer to the object if it exists in the context of the
|
||||
* registry, a null pointer otherwise.
|
||||
*/
|
||||
template<typename Type>
|
||||
[[nodiscard]] std::add_const_t<Type> *try_ctx() const {
|
||||
auto it = vars.find(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value());
|
||||
return it == vars.cend() ? nullptr : any_cast<std::add_const_t<Type>>(&it->second);
|
||||
}
|
||||
|
||||
/*! @copydoc try_ctx */
|
||||
template<typename Type>
|
||||
[[nodiscard]] Type *try_ctx() {
|
||||
auto it = vars.find(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value());
|
||||
return it == vars.end() ? nullptr : any_cast<Type>(&it->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to an object in the context of the registry.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to get a context variable that doesn't exist results in
|
||||
* undefined behavior.
|
||||
*
|
||||
* @tparam Type Type of object to get.
|
||||
* @return A valid reference to the object in the context of the registry.
|
||||
*/
|
||||
template<typename Type>
|
||||
[[nodiscard]] std::add_const_t<Type> &ctx() const {
|
||||
return any_cast<std::add_const_t<Type> &>(vars.at(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()));
|
||||
context &ctx() ENTT_NOEXCEPT {
|
||||
return vars;
|
||||
}
|
||||
|
||||
/*! @copydoc ctx */
|
||||
template<typename Type>
|
||||
[[nodiscard]] Type &ctx() {
|
||||
return any_cast<Type &>(vars.at(type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visits a registry and returns the type info for its context
|
||||
* variables.
|
||||
*
|
||||
* The signature of the function should be equivalent to the following:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* void(const type_info &);
|
||||
* @endcode
|
||||
*
|
||||
* Returned identifiers are those of the context variables currently set.
|
||||
*
|
||||
* @sa type_info
|
||||
*
|
||||
* @tparam Func Type of the function object to invoke.
|
||||
* @param func A valid function object.
|
||||
*/
|
||||
template<typename Func>
|
||||
void ctx(Func func) const {
|
||||
for(auto &&curr: vars) {
|
||||
func(curr.second.type());
|
||||
}
|
||||
const context &ctx() const ENTT_NOEXCEPT {
|
||||
return vars;
|
||||
}
|
||||
|
||||
private:
|
||||
dense_hash_map<id_type, std::unique_ptr<base_type>, identity> pools{};
|
||||
dense_hash_map<id_type, basic_any<0u>, identity> vars{};
|
||||
std::vector<group_data> groups{};
|
||||
std::vector<entity_type> entities{};
|
||||
entity_type free_list{tombstone};
|
||||
context vars;
|
||||
};
|
||||
|
||||
} // namespace entt
|
||||
|
||||
@@ -358,17 +358,17 @@ TEST(Organizer, Prepare) {
|
||||
|
||||
const auto graph = organizer.graph();
|
||||
|
||||
ASSERT_EQ(registry.try_ctx<int>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_FALSE(registry.ctx().contains<int>());
|
||||
ASSERT_FALSE(registry.ctx().contains<char>());
|
||||
ASSERT_FALSE(registry.ctx().contains<double>());
|
||||
|
||||
for(auto &&vertex: graph) {
|
||||
vertex.prepare(registry);
|
||||
}
|
||||
|
||||
ASSERT_EQ(registry.try_ctx<int>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_NE(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_FALSE(registry.ctx().contains<int>());
|
||||
ASSERT_FALSE(registry.ctx().contains<char>());
|
||||
ASSERT_TRUE(registry.ctx().contains<double>());
|
||||
}
|
||||
|
||||
TEST(Organizer, Dependencies) {
|
||||
@@ -422,10 +422,10 @@ TEST(Organizer, ToArgsIntegrity) {
|
||||
entt::registry registry;
|
||||
|
||||
organizer.emplace<&to_args_integrity>();
|
||||
registry.set<std::size_t>(42u);
|
||||
registry.ctx().emplace<std::size_t>(42u);
|
||||
|
||||
auto graph = organizer.graph();
|
||||
graph[0u].callback()(graph[0u].data(), registry);
|
||||
|
||||
ASSERT_EQ(registry.ctx<std::size_t>(), 0u);
|
||||
ASSERT_EQ(registry.ctx().at<std::size_t>(), 0u);
|
||||
}
|
||||
|
||||
@@ -64,95 +64,84 @@ struct owner {
|
||||
|
||||
TEST(Registry, Context) {
|
||||
entt::registry registry;
|
||||
auto &ctx = registry.ctx();
|
||||
const auto &cctx = std::as_const(registry).ctx();
|
||||
|
||||
ASSERT_EQ(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_FALSE(ctx.contains<char>());
|
||||
ASSERT_FALSE(cctx.contains<const int>());
|
||||
ASSERT_EQ(ctx.find<char>(), nullptr);
|
||||
ASSERT_EQ(cctx.find<const int>(), nullptr);
|
||||
|
||||
registry.set<char>();
|
||||
registry.set<int>();
|
||||
// suppress the warning due to the [[nodiscard]] attribute
|
||||
static_cast<void>(registry.ctx_or_set<double>());
|
||||
ctx.emplace<char>();
|
||||
ctx.emplace<int>();
|
||||
|
||||
ASSERT_NE(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_NE(registry.try_ctx<const int>(), nullptr);
|
||||
ASSERT_NE(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_TRUE(ctx.contains<char>());
|
||||
ASSERT_TRUE(cctx.contains<int>());
|
||||
ASSERT_NE(ctx.find<const char>(), nullptr);
|
||||
ASSERT_NE(cctx.find<const int>(), nullptr);
|
||||
|
||||
registry.unset<int>();
|
||||
registry.unset<double>();
|
||||
ctx.erase<int>();
|
||||
|
||||
auto count = 0;
|
||||
ASSERT_TRUE(ctx.contains<const char>());
|
||||
ASSERT_FALSE(cctx.contains<const int>());
|
||||
ASSERT_NE(ctx.find<char>(), nullptr);
|
||||
ASSERT_EQ(cctx.find<int>(), nullptr);
|
||||
|
||||
registry.ctx([&count](const auto &info) {
|
||||
ASSERT_EQ(info.hash(), entt::type_hash<char>::value());
|
||||
++count;
|
||||
});
|
||||
ctx.erase<char>();
|
||||
ctx.emplace<char>('c');
|
||||
ctx.emplace<int>(42);
|
||||
;
|
||||
|
||||
ASSERT_EQ(count, 1);
|
||||
ASSERT_EQ(ctx.emplace<char>('a'), 'c');
|
||||
ASSERT_EQ(ctx.find<const char>(), cctx.find<char>());
|
||||
ASSERT_EQ(ctx.at<char>(), cctx.at<const char>());
|
||||
ASSERT_EQ(ctx.at<char>(), 'c');
|
||||
|
||||
ASSERT_NE(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_EQ(ctx.emplace<const int>(0), 42);
|
||||
ASSERT_EQ(ctx.find<const int>(), cctx.find<int>());
|
||||
ASSERT_EQ(ctx.at<int>(), cctx.at<const int>());
|
||||
ASSERT_EQ(ctx.at<int>(), 42);
|
||||
|
||||
registry.set<char>('c');
|
||||
registry.set<int>(0);
|
||||
registry.set<double>(1.);
|
||||
registry.set<int>(42);
|
||||
|
||||
ASSERT_EQ(registry.ctx_or_set<char>('a'), 'c');
|
||||
ASSERT_NE(registry.try_ctx<char>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<char>(), ®istry.ctx<char>());
|
||||
ASSERT_EQ(registry.ctx<char>(), std::as_const(registry).ctx<const char>());
|
||||
|
||||
ASSERT_EQ(registry.ctx<const int>(), 42);
|
||||
ASSERT_NE(registry.try_ctx<int>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<const int>(), ®istry.ctx<int>());
|
||||
ASSERT_EQ(registry.ctx<int>(), std::as_const(registry).ctx<const int>());
|
||||
|
||||
ASSERT_EQ(registry.ctx<const double>(), 1.);
|
||||
ASSERT_NE(registry.try_ctx<double>(), nullptr);
|
||||
ASSERT_EQ(registry.try_ctx<const double>(), ®istry.ctx<double>());
|
||||
ASSERT_EQ(registry.ctx<double>(), std::as_const(registry).ctx<const double>());
|
||||
|
||||
ASSERT_EQ(registry.try_ctx<float>(), nullptr);
|
||||
ASSERT_EQ(ctx.find<double>(), nullptr);
|
||||
ASSERT_EQ(cctx.find<double>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(Registry, ContextAsRef) {
|
||||
entt::registry registry;
|
||||
int value{3};
|
||||
|
||||
registry.set<int &>(value);
|
||||
registry.ctx().emplace<int &>(value);
|
||||
|
||||
ASSERT_NE(registry.try_ctx<int>(), nullptr);
|
||||
ASSERT_NE(registry.try_ctx<const int>(), nullptr);
|
||||
ASSERT_NE(std::as_const(registry).try_ctx<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.ctx<const int>(), 3);
|
||||
ASSERT_EQ(registry.ctx<int>(), 3);
|
||||
ASSERT_NE(registry.ctx().find<int>(), nullptr);
|
||||
ASSERT_NE(registry.ctx().find<const int>(), nullptr);
|
||||
ASSERT_NE(std::as_const(registry).ctx().find<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.ctx().at<const int>(), 3);
|
||||
ASSERT_EQ(registry.ctx().at<int>(), 3);
|
||||
|
||||
registry.ctx<int>() = 42;
|
||||
registry.ctx().at<int>() = 42;
|
||||
|
||||
ASSERT_EQ(registry.ctx<int>(), 42);
|
||||
ASSERT_EQ(registry.ctx().at<int>(), 42);
|
||||
ASSERT_EQ(value, 42);
|
||||
|
||||
value = 3;
|
||||
|
||||
ASSERT_EQ(std::as_const(registry).ctx<const int>(), 3);
|
||||
ASSERT_EQ(std::as_const(registry).ctx().at<const int>(), 3);
|
||||
}
|
||||
|
||||
TEST(Registry, ContextAsConstRef) {
|
||||
entt::registry registry;
|
||||
int value{3};
|
||||
|
||||
registry.set<const int &>(value);
|
||||
registry.ctx().emplace<const int &>(value);
|
||||
|
||||
ASSERT_EQ(registry.try_ctx<int>(), nullptr);
|
||||
ASSERT_NE(registry.try_ctx<const int>(), nullptr);
|
||||
ASSERT_NE(std::as_const(registry).try_ctx<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.ctx<const int>(), 3);
|
||||
ASSERT_EQ(registry.ctx().find<int>(), nullptr);
|
||||
ASSERT_NE(registry.ctx().find<const int>(), nullptr);
|
||||
ASSERT_NE(std::as_const(registry).ctx().find<const int>(), nullptr);
|
||||
ASSERT_EQ(registry.ctx().at<const int>(), 3);
|
||||
|
||||
value = 42;
|
||||
|
||||
ASSERT_EQ(std::as_const(registry).ctx<const int>(), 42);
|
||||
ASSERT_EQ(std::as_const(registry).ctx().at<const int>(), 42);
|
||||
}
|
||||
|
||||
TEST(Registry, Functionalities) {
|
||||
@@ -1762,11 +1751,11 @@ TEST(Registry, Constness) {
|
||||
static_assert((std::is_same_v<decltype(registry.try_get<int>({})), int *>));
|
||||
static_assert((std::is_same_v<decltype(registry.try_get<int, const char>({})), std::tuple<int *, const char *>>));
|
||||
|
||||
static_assert((std::is_same_v<decltype(registry.ctx<int>()), int &>));
|
||||
static_assert((std::is_same_v<decltype(registry.ctx<const char>()), const char &>));
|
||||
static_assert((std::is_same_v<decltype(registry.ctx().at<int>()), int &>));
|
||||
static_assert((std::is_same_v<decltype(registry.ctx().at<const char>()), const char &>));
|
||||
|
||||
static_assert((std::is_same_v<decltype(registry.try_ctx<int>()), int *>));
|
||||
static_assert((std::is_same_v<decltype(registry.try_ctx<const char>()), const char *>));
|
||||
static_assert((std::is_same_v<decltype(registry.ctx().find<int>()), int *>));
|
||||
static_assert((std::is_same_v<decltype(registry.ctx().find<const char>()), const char *>));
|
||||
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).get<int>({})), const int &>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).get<int, const char>({})), std::tuple<const int &, const char &>>));
|
||||
@@ -1774,11 +1763,11 @@ TEST(Registry, Constness) {
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).try_get<int>({})), const int *>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).try_get<int, const char>({})), std::tuple<const int *, const char *>>));
|
||||
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx<int>()), const int &>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx<const char>()), const char &>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().at<int>()), const int &>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().at<const char>()), const char &>));
|
||||
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).try_ctx<int>()), const int *>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).try_ctx<const char>()), const char *>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().find<int>()), const int *>));
|
||||
static_assert((std::is_same_v<decltype(std::as_const(registry).ctx().find<const char>()), const char *>));
|
||||
}
|
||||
|
||||
TEST(Registry, MoveOnlyComponent) {
|
||||
|
||||
Reference in New Issue
Block a user