more on context variables

This commit is contained in:
Michele Caini
2019-03-21 22:04:55 +01:00
parent 420fc9aa24
commit e7f2c6b5ba
4 changed files with 30 additions and 32 deletions

1
TODO
View File

@@ -21,3 +21,4 @@
* add a sort of "fast each" for when users know they are not to add/remove components, it can use directly raw access and improve even further performance
* types defined at runtime that refer to the same compile-time type (but to different pools) are possible, the library is almost there
* view/group iterators that return entities and components? I'd still like to have it :-)
* use try_get in the multi component view (each), it should have better perf

View File

@@ -838,15 +838,16 @@ newly created instance later on:
// creates a new context variable initialized with the given values
registry.set<my_type>(42, 'c');
// gets a context variable associated with a registry
auto &var = registry.ctx<my_type>();
if(auto *var = registry.ctx<my_type>(); var) {
// uses the context variable associated with a registry, if any
}
```
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. The `ctx` member
function requires that the context variable exist to work properly and doesn't
create it silently under the hood.
function returns a pointer to the context variable if it exists, otherwise it
returns a null pointer. This fits well with the `if` statement with initializer.
# Views and Groups

View File

@@ -1605,7 +1605,8 @@ public:
std::swap(vars[ctype], vars.back());
wrapper = vars[ctype].get();
} else if(!wrapper) {
wrapper = vars.emplace_back(std::make_unique<type_wrapper<Type>>()).get();
vars[ctype] = std::make_unique<type_wrapper<Type>>();
wrapper = vars[ctype].get();
}
}
@@ -1617,19 +1618,13 @@ public:
}
/**
* @brief Returns a reference to an object in the context of the registry.
*
* @warning
* Attempting to get an object that doesn't exist in the context of the
* registry results in undefined behavior.<br/>
* An assertion will abort the execution at runtime in debug mode if the
* object isn't part of the context of the registry.
*
* @brief Returns a pointer to an object in the context of the registry.
* @tparam Type Type of object to get.
* @return A reference to the object.
* @return A pointer to the object if it exists in the context of the
* registry, a null pointer otherwise.
*/
template<typename Type>
const Type & ctx() const ENTT_NOEXCEPT {
const Type * ctx() const ENTT_NOEXCEPT {
const auto ctype = runtime_type<Type, context_family>();
if constexpr(is_named_type_v<Type>) {
@@ -1637,18 +1632,17 @@ public:
return candidate && candidate->runtime_type == ctype;
});
assert(it != vars.cend());
return static_cast<const type_wrapper<Type> *>(it->get())->value;
return (it == vars.cend()) ? nullptr : &static_cast<const type_wrapper<Type> &>(**it).value;
} else {
assert(ctype < vars.size() && vars[ctype] && vars[ctype]->runtime_type == ctype);
return static_cast<const type_wrapper<Type> *>(vars[ctype].get())->value;
const bool valid = ctype < vars.size() && vars[ctype] && vars[ctype]->runtime_type == ctype;
return valid ? &static_cast<const type_wrapper<Type> &>(*vars[ctype]).value : nullptr;
}
}
/*! @copydoc ctx */
template<typename Type>
Type & ctx() ENTT_NOEXCEPT {
return const_cast<Type &>(std::as_const(*this).template ctx<Type>());
Type * ctx() ENTT_NOEXCEPT {
return const_cast<Type *>(std::as_const(*this).template ctx<Type>());
}
private:

View File

@@ -35,22 +35,24 @@ struct listener {
TEST(Registry, Context) {
entt::registry registry;
const auto &ivalue = registry.set<int>(0);
const auto &cvalue = registry.set<char>('c');
const auto &dvalue = registry.set<double>(1.);
registry.set<char>('c');
registry.set<int>(0);
registry.set<double>(1.);
registry.set<int>(42);
ASSERT_EQ(ivalue, 42);
ASSERT_EQ(ivalue, registry.ctx<int>());
ASSERT_EQ(registry.ctx<int>(), std::as_const(registry).ctx<int>());
ASSERT_EQ(cvalue, 'c');
ASSERT_EQ(cvalue, registry.ctx<char>());
ASSERT_EQ(*registry.ctx<char>(), 'c');
ASSERT_NE(registry.ctx<char>(), nullptr);
ASSERT_EQ(registry.ctx<char>(), std::as_const(registry).ctx<char>());
ASSERT_EQ(dvalue, 1.);
ASSERT_EQ(dvalue, registry.ctx<double>());
ASSERT_EQ(*registry.ctx<int>(), 42);
ASSERT_NE(registry.ctx<int>(), nullptr);
ASSERT_EQ(registry.ctx<int>(), std::as_const(registry).ctx<int>());
ASSERT_EQ(*registry.ctx<double>(), 1.);
ASSERT_NE(registry.ctx<double>(), nullptr);
ASSERT_EQ(registry.ctx<double>(), std::as_const(registry).ctx<double>());
ASSERT_EQ(registry.ctx<float>(), nullptr);
}
TEST(Registry, Types) {