*: added meaningful messages (?) to static asserts (close #493)

This commit is contained in:
Michele Caini
2020-05-24 00:32:08 +02:00
parent 7db0f540bd
commit 5fbb663529
18 changed files with 45 additions and 56 deletions

View File

@@ -80,7 +80,7 @@ struct insertion_sort {
*/
template<std::size_t Bit, std::size_t N>
struct radix_sort {
static_assert((N % Bit) == 0);
static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass");
/**
* @brief Sorts the elements in a range.

View File

@@ -46,7 +46,7 @@ class identifier {
template<typename Type, std::size_t... Indexes>
static constexpr id_type get(std::index_sequence<Indexes...>) {
static_assert(std::disjunction_v<std::is_same<Type, Types>...>);
static_assert(std::disjunction_v<std::is_same<Type, Types>...>, "Invalid type");
return (0 + ... + (std::is_same_v<Type, std::tuple_element_t<Indexes, tuple_type>> ? id_type(Indexes) : id_type{}));
}

View File

@@ -193,7 +193,7 @@ inline constexpr auto is_equality_comparable_v = is_equality_comparable<Type>::v
*/
template<typename Member>
class member_class {
static_assert(std::is_member_pointer_v<Member>);
static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function");
template<typename Class, typename Ret, typename... Args>
static Class * clazz(Ret(Class:: *)(Args...));

View File

@@ -385,7 +385,7 @@ public:
template<typename... Component, typename Compare, typename Sort = std_sort, typename... Args>
void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
if constexpr(sizeof...(Component) == 0) {
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>);
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
handler->sort(handler->begin(), handler->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
} else if constexpr(sizeof...(Component) == 1) {
handler->sort(handler->begin(), handler->end(), [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {
@@ -812,7 +812,7 @@ public:
auto *cpool = std::get<0>(pools);
if constexpr(sizeof...(Component) == 0) {
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>);
static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function");
cpool->sort(cpool->end()-*length, cpool->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
} else if constexpr(sizeof...(Component) == 1) {
cpool->sort(cpool->end()-*length, cpool->end(), [this, compare = std::move(compare)](const entity_type lhs, const entity_type rhs) {

View File

@@ -122,7 +122,7 @@ as_group(const basic_registry<Entity> &) ENTT_NOEXCEPT -> as_group<true, Entity>
*/
template<auto Member, typename Entity = entity>
void invoke(basic_registry<Entity> &reg, const Entity entt) {
static_assert(std::is_member_function_pointer_v<decltype(Member)>);
static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
delegate<void(basic_registry<Entity> &, const Entity)> func;
func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
func(reg, entt);

View File

@@ -257,7 +257,7 @@ class basic_observer {
template<typename... Matcher, std::size_t... Index>
void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits, "Too many matchers");
(matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
release = &basic_observer::disconnect<Matcher...>;
}
@@ -408,8 +408,6 @@ public:
*/
template<typename Func>
void each(Func func) const {
static_assert(std::is_invocable_v<Func, entity_type>);
for(const auto entity: *this) {
func(entity);
}

View File

@@ -45,7 +45,7 @@ class basic_registry {
template<typename Component>
struct pool_handler final: storage<Entity, Component> {
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Invalid component type");
std::size_t super{};
auto on_construct() ENTT_NOEXCEPT {
@@ -129,12 +129,11 @@ class basic_registry {
template<typename... Exclude, typename... Get, typename... Owned>
struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
static_assert(std::conjunction_v<std::is_same<Owned, std::decay_t<Owned>>..., std::is_same<Get, std::decay_t<Get>>..., std::is_same<Exclude, std::decay_t<Exclude>>...>);
static_assert(std::conjunction_v<std::is_same<Owned, std::decay_t<Owned>>..., std::is_same<Get, std::decay_t<Get>>..., std::is_same<Exclude, std::decay_t<Exclude>>...>, "One or more component types are invalid");
std::conditional_t<sizeof...(Owned) == 0, sparse_set<Entity>, std::size_t> current{};
template<typename Component>
void maybe_valid_if(basic_registry &owner, const Entity entt) {
static_assert(std::disjunction_v<std::is_same<Owned, std::decay_t<Owned>>..., std::is_same<Get, std::decay_t<Get>>..., std::is_same<Exclude, std::decay_t<Exclude>>...>);
[[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<pool_handler<Owned> &>(cpools).contains(entt)) && ...)
@@ -182,7 +181,6 @@ class basic_registry {
template<typename Component>
const pool_handler<Component> & assure() const {
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
const sparse_set<entity_type> *cpool;
if constexpr(has_type_index_v<Component>) {
@@ -674,7 +672,7 @@ public:
*/
template<typename Component, typename EIt, typename CIt>
void insert(EIt first, EIt last, CIt from, CIt to) {
static_assert(std::is_constructible_v<Component, typename std::iterator_traits<CIt>::value_type>);
static_assert(std::is_constructible_v<Component, typename std::iterator_traits<CIt>::value_type>, "Invalid value type");
ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); }));
assure<Component>().insert(*this, first, last, from, to);
}
@@ -1035,8 +1033,6 @@ public:
*/
template<typename Func>
void each(Func func) const {
static_assert(std::is_invocable_v<Func, entity_type>);
if(destroyed == null) {
for(auto pos = entities.size(); pos; --pos) {
func(entities[pos-1]);
@@ -1078,8 +1074,6 @@ public:
*/
template<typename Func>
void orphans(Func func) const {
static_assert(std::is_invocable_v<Func, entity_type>);
each([this, &func](const auto entity) {
if(orphan(entity)) {
func(entity);
@@ -1296,14 +1290,14 @@ public:
*/
template<typename... Component, typename... Exclude>
entt::basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) const {
static_assert(sizeof...(Component) > 0);
static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
return { assure<std::decay_t<Component>>()..., assure<Exclude>()... };
}
/*! @copydoc view */
template<typename... Component, typename... Exclude>
entt::basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) {
static_assert(sizeof...(Component) > 0);
static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
return { assure<std::decay_t<Component>>()..., assure<Exclude>()... };
}
@@ -1347,8 +1341,8 @@ public:
*/
template<typename... Owned, typename... Get, typename... Exclude>
entt::basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> group(get_t<Get...>, exclude_t<Exclude...> = {}) {
static_assert(sizeof...(Owned) + sizeof...(Get) > 0);
static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1);
static_assert(sizeof...(Owned) + sizeof...(Get) > 0, "Exclusion-only views are not supported");
static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1, "Single component groups are not allowed");
using handler_type = group_handler<exclude_t<Exclude...>, get_t<std::decay_t<Get>...>, std::decay_t<Owned>...>;
@@ -1443,7 +1437,7 @@ public:
*/
template<typename... Owned, typename... Get, typename... Exclude>
entt::basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> group(get_t<Get...>, exclude_t<Exclude...> = {}) const {
static_assert(std::conjunction_v<std::is_const<Owned>..., std::is_const<Get>...>);
static_assert(std::conjunction_v<std::is_const<Owned>..., std::is_const<Get>...>, "Invalid non-const type");
return const_cast<basic_registry *>(this)->group<Owned...>(entt::get<Get...>, exclude<Exclude...>);
}
@@ -1472,7 +1466,7 @@ public:
*/
template<typename... Owned, typename... Exclude>
entt::basic_group<Entity, exclude_t<Exclude...>, get_t<>, Owned...> group(exclude_t<Exclude...> = {}) const {
static_assert(std::conjunction_v<std::is_const<Owned>...>);
static_assert(std::conjunction_v<std::is_const<Owned>...>, "Invalid non-const type");
return const_cast<basic_registry *>(this)->group<Owned...>(exclude<Exclude...>);
}

View File

@@ -336,7 +336,7 @@ class basic_continuous_loader {
} else if constexpr(std::is_same_v<first_type, entity_type>) {
other.emplace(map(pair.first), std::move(pair.second));
} else {
static_assert(std::is_same_v<second_type, entity_type>);
static_assert(std::is_same_v<second_type, entity_type>, "Neither the key nor the value are of entity type");
other.emplace(std::move(pair.first), map(pair.second));
}
}
@@ -348,7 +348,7 @@ class basic_continuous_loader {
auto update(char, Container &container)
-> decltype(typename Container::value_type{}, void()) {
// vector like container
static_assert(std::is_same_v<typename Container::value_type, entity_type>);
static_assert(std::is_same_v<typename Container::value_type, entity_type>, "Invalid value type");
for(auto &&entt: container) {
entt = map(entt);

View File

@@ -41,7 +41,7 @@ namespace entt {
*/
template<typename Entity>
class sparse_set {
static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0), "ENTT_PAGE_SIZE must be a power of two");
static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(Entity);
using traits_type = entt_traits<std::underlying_type_t<Entity>>;

View File

@@ -46,8 +46,7 @@ namespace entt {
*/
template<typename Entity, typename Type, typename = std::void_t<>>
class storage: public sparse_set<Entity> {
static_assert(std::is_move_constructible_v<Type>);
static_assert(std::is_move_assignable_v<Type>);
static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The managed type must be at least move constructible and assignable");
using underlying_type = sparse_set<Entity>;
using traits_type = entt_traits<std::underlying_type_t<Entity>>;

View File

@@ -405,7 +405,7 @@ public:
ENTT_ASSERT(contains(entt));
if constexpr(sizeof...(Comp) == 0) {
static_assert(sizeof...(Component) == 1);
static_assert(sizeof...(Component) == 1, "Invalid component type");
return (std::get<pool_type<Component> *>(pools)->get(entt), ...);
} else if constexpr(sizeof...(Comp) == 1) {
return (std::get<pool_type<Comp> *>(pools)->get(entt), ...);
@@ -672,7 +672,7 @@ public:
*/
template<typename Comp = Component>
decltype(auto) get(const entity_type entt) const {
static_assert(std::is_same_v<Comp, Component>);
static_assert(std::is_same_v<Comp, Component>, "Invalid component type");
ENTT_ASSERT(contains(entt));
return pool->get(entt);
}

View File

@@ -96,7 +96,7 @@ bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index,
if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
using helper_type = meta_function_helper_t<decltype(Data)>;
using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>, "Invalid function or member function");
auto * const clazz = instance.try_cast<Type>();
auto * const direct = value.try_cast<data_type>();
@@ -106,7 +106,7 @@ bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index,
}
} else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
static_assert(std::is_invocable_v<decltype(Data), Type *>);
static_assert(std::is_invocable_v<decltype(Data), Type *>, "Invalid data member");
auto * const clazz = instance.try_cast<Type>();
if constexpr(std::is_array_v<data_type>) {
@@ -127,7 +127,7 @@ bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index,
}
}
} else {
static_assert(std::is_pointer_v<decltype(Data)>);
static_assert(std::is_pointer_v<decltype(Data)>, "Invalid pointer to data type");
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*Data)>>;
if constexpr(std::is_array_v<data_type>) {
@@ -162,18 +162,18 @@ meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any in
} else if constexpr(std::is_same_v<Policy, as_ref_t>) {
return meta_any{std::ref(std::forward<decltype(value)>(value))};
} else {
static_assert(std::is_same_v<Policy, as_is_t>);
static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
return meta_any{std::forward<decltype(value)>(value)};
}
};
if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
static_assert(std::is_invocable_v<decltype(Data), Type &>);
static_assert(std::is_invocable_v<decltype(Data), Type &>, "Invalid function or member function");
auto * const clazz = instance.try_cast<Type>();
return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
} else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
static_assert(std::is_invocable_v<decltype(Data), Type *>);
static_assert(std::is_invocable_v<decltype(Data), Type *>, "Invalid data member");
auto * const clazz = instance.try_cast<Type>();
if constexpr(std::is_array_v<data_type>) {
@@ -183,7 +183,7 @@ meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any in
return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
}
} else {
static_assert(std::is_pointer_v<std::decay_t<decltype(Data)>>);
static_assert(std::is_pointer_v<std::decay_t<decltype(Data)>>, "Invalid pointer to data type");
if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
auto * const idx = index.try_cast<std::size_t>();
@@ -206,7 +206,7 @@ meta_any invoke([[maybe_unused]] meta_any instance, meta_any *args, std::index_s
} else if constexpr(std::is_same_v<Policy, as_ref_t>) {
return meta_any{std::ref(std::invoke(Candidate, *params...))};
} else {
static_assert(std::is_same_v<Policy, as_is_t>);
static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
return meta_any{std::invoke(Candidate, *params...)};
}
};
@@ -402,7 +402,6 @@ public:
return meta_factory<Type, Type>{&node->prop};
}
/*! @copydoc type */
/**
* @brief Assigns a meta base to a meta type.
*
@@ -413,7 +412,7 @@ public:
*/
template<typename Base>
auto base() ENTT_NOEXCEPT {
static_assert(std::is_base_of_v<Base, Type>);
static_assert(std::is_base_of_v<Base, Type>, "Invalid base type");
auto * const type = internal::meta_info<Type>::resolve();
static internal::meta_base_node node{
@@ -443,7 +442,7 @@ public:
*/
template<typename To>
auto conv() ENTT_NOEXCEPT {
static_assert(std::is_convertible_v<Type, To>);
static_assert(std::is_convertible_v<Type, To>, "Could not convert to the required type");
auto * const type = internal::meta_info<Type>::resolve();
static internal::meta_conv_node node{
@@ -511,7 +510,7 @@ public:
template<auto Func, typename Policy = as_is_t>
auto ctor() ENTT_NOEXCEPT {
using helper_type = internal::meta_function_helper_t<decltype(Func)>;
static_assert(std::is_same_v<typename helper_type::return_type, Type>);
static_assert(std::is_same_v<typename helper_type::return_type, Type>, "The function doesn't return an object of the required type");
auto * const type = internal::meta_info<Type>::resolve();
static internal::meta_ctor_node node{
@@ -583,7 +582,7 @@ public:
*/
template<auto Func>
auto dtor() ENTT_NOEXCEPT {
static_assert(std::is_invocable_v<decltype(Func), Type &>);
static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
auto * const type = internal::meta_info<Type>::resolve();
static internal::meta_dtor_node node{
@@ -620,7 +619,7 @@ public:
internal::meta_data_node *curr = nullptr;
if constexpr(std::is_same_v<Type, decltype(Data)>) {
static_assert(std::is_same_v<Policy, as_is_t>);
static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
static internal::meta_data_node node{
{},
@@ -652,7 +651,6 @@ public:
curr = &node;
} else {
static_assert(std::is_pointer_v<std::decay_t<decltype(Data)>>);
using data_type = std::remove_pointer_t<std::decay_t<decltype(Data)>>;
static internal::meta_data_node node{
@@ -702,7 +700,7 @@ public:
template<auto Setter, auto Getter, typename Policy = as_is_t>
auto data(const id_type id) ENTT_NOEXCEPT {
using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>);
static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>, "Invalid setter and/or getter");
auto * const type = internal::meta_info<Type>::resolve();
static internal::meta_data_node node{

View File

@@ -222,7 +222,7 @@ struct ENTT_API meta_context {
template<typename Type>
struct ENTT_API meta_node {
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>);
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
static meta_type_node * resolve() ENTT_NOEXCEPT {
static meta_type_node node{
@@ -670,7 +670,7 @@ struct meta_handle {
if constexpr(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>) {
any = *value;
} else {
static_assert(std::is_lvalue_reference_v<Type>);
static_assert(std::is_lvalue_reference_v<Type>, "Lvalue reference required");
any = std::ref(value);
}
}

View File

@@ -169,7 +169,7 @@ public:
/*! @brief Default destructor. */
virtual ~process() {
static_assert(std::is_base_of_v<process, Derived>);
static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template");
}
/**

View File

@@ -63,7 +63,7 @@ class scheduler {
template<typename Proc, typename... Args>
continuation then(Args &&... args) {
static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>);
static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
handler->next.reset(new process_handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr});
handler = handler->next.get();
@@ -175,7 +175,7 @@ public:
*/
template<typename Proc, typename... Args>
auto attach(Args &&... args) {
static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>);
static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type");
auto proc = typename process_handler::instance_type{new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
process_handler handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>, nullptr};
// forces the process to exit the uninitialized state

View File

@@ -92,7 +92,7 @@ struct cache {
*/
template<typename Loader, typename... Args>
entt::handle<Resource> load(const id_type id, Args &&... args) {
static_assert(std::is_base_of_v<loader<Loader, Resource>, Loader>);
static_assert(std::is_base_of_v<loader<Loader, Resource>, Loader>, "Invalid loader type");
entt::handle<Resource> resource{};
if(auto it = resources.find(id); it == resources.cend()) {

View File

@@ -84,7 +84,7 @@ class dispatcher {
template<typename Event>
pool_handler<Event> & assure() {
static_assert(std::is_same_v<Event, std::decay_t<Event>>);
static_assert(std::is_same_v<Event, std::decay_t<Event>>, "Invalid event type");
if constexpr(has_type_index_v<Event>) {
const auto index = type_index<Event>::value();

View File

@@ -126,7 +126,7 @@ class emitter {
template<typename Event>
const pool_handler<Event> & assure() const {
static_assert(std::is_same_v<Event, std::decay_t<Event>>);
static_assert(std::is_same_v<Event, std::decay_t<Event>>, "Invalid event type");
if constexpr(has_type_index_v<Event>) {
const auto index = type_index<Event>::value();
@@ -187,7 +187,7 @@ public:
/*! @brief Default destructor. */
virtual ~emitter() {
static_assert(std::is_base_of_v<emitter<Derived>, Derived>);
static_assert(std::is_base_of_v<emitter<Derived>, Derived>, "Incorrect use of the class template");
}
/*! @brief Default move constructor. */