-
Notifications
You must be signed in to change notification settings - Fork 493
genericize DataIdentity for container types
#4591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 13 commits
63a35c3
9701cf8
d7edcce
b6af192
0c7dab2
20d645c
4aea762
93d9977
ed44b01
95116d5
2b25eb6
0afd6a9
bea43f6
7ce040b
6944ca6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -34,6 +34,8 @@ distribution. | |||||
| #include <variant> | ||||||
| #include <vector> | ||||||
| #include <variant> | ||||||
| #include <ranges> | ||||||
| #include <array> | ||||||
|
|
||||||
| #include "DataDefs.h" | ||||||
|
|
||||||
|
|
@@ -113,10 +115,10 @@ namespace DFHack | |||||
|
|
||||||
| class DFHACK_EXPORT container_identity : public constructed_identity { | ||||||
| type_identity *item; | ||||||
| enum_identity *ienum; | ||||||
| type_identity *ienum; | ||||||
|
|
||||||
| public: | ||||||
| container_identity(size_t size, TAllocateFn alloc, type_identity *item, enum_identity *ienum = NULL) | ||||||
| container_identity(size_t size, TAllocateFn alloc, type_identity *item, type_identity *ienum = NULL) | ||||||
| : constructed_identity(size, alloc), item(item), ienum(ienum) {}; | ||||||
|
|
||||||
| virtual identity_type type() { return IDTYPE_CONTAINER; } | ||||||
|
|
@@ -190,6 +192,102 @@ namespace DFHack | |||||
| virtual bool get_item(void *ptr, int idx) = 0; | ||||||
| virtual void set_item(void *ptr, int idx, bool val) = 0; | ||||||
| }; | ||||||
|
|
||||||
| template <typename C> | ||||||
| concept isIndexedContainer = requires (C c, C::size_type sz) { | ||||||
| { c[sz] } -> std::same_as<typename C::reference>; | ||||||
| { c.size() } ->std::same_as<typename C::size_type>; | ||||||
| { c.begin() } -> std::same_as<typename C::iterator>; | ||||||
| { c.end() } -> std::same_as<typename C::iterator>; | ||||||
| }; | ||||||
|
|
||||||
| template <typename C> | ||||||
| concept isResizableContainer = isIndexedContainer<C> && requires (C c, C::iterator i, C::size_type sz, C::value_type v) { | ||||||
| { c.erase(i) }; | ||||||
| { c.resize(sz) }; | ||||||
| { c.insert(i, v) }; | ||||||
| }; | ||||||
|
|
||||||
| template<isIndexedContainer C> | ||||||
| class generic_container_identity : public container_identity { | ||||||
| private: | ||||||
| using T = C::value_type; | ||||||
|
|
||||||
| template<typename T> struct type_name { | ||||||
| static const inline std::string name = "container"; | ||||||
| }; | ||||||
| template<typename T> struct type_name<std::vector<T>> { | ||||||
| static const inline std::string name = "vector"; | ||||||
| }; | ||||||
| template<typename T> struct type_name<std::deque<T>> { | ||||||
| static const inline std::string name = "deque"; | ||||||
| }; | ||||||
| template<typename T, int sz> struct type_name<std::array<T, sz>> { | ||||||
|
||||||
| template<typename T, int sz> struct type_name<std::array<T, sz>> { | |
| template<typename T, size_t sz> struct type_name<std::array<T, sz>> { |
to match properly.
I am debating removing the name = "container" from the base template to catch this sort of thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's what I was testing with: DFHack/df-structures#757
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am debating removing the
name = "container"from the base template to catch this sort of thing.
i was ambivalent on that issue originally. it's not hard for us to add a new specialization but it's more of a burden for a developer of an external plugin. maybe only include the generic case in the library build? that would cause any unspecialized in core code to error at compile time, while allowing plugin developers freedom to use specialized containers for their own purposes (although i'm not sure what the scenario for that is, tbh) nah i don't think that does what i want.. maybe someone else would have a better idea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Support for adding new types in plugins is limited anyway. Their identities won't be registered in the global registry tables in #4591 (comment) (although I'm a little unsure whether any container types are registered there).
Really, my intent of breaking the base template would be to catch specializations like array<T, int> that are intended to work but don't. It took me a while to figure out why a std::array was printing as "container" instead of "array".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious why this changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specifically because of associative containers, the identity key type of an associative container goes there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I wonder if there is a way to enforce that this is an
enum_identityfor non-associative containers. Probably complicated.