{"action":"created","issue":{"url":"https://api.github.com/repos/skypjack/entt/issues/152","repository_url":"https://api.github.com/repos/skypjack/entt","labels_url":"https://api.github.com/repos/skypjack/entt/issues/152/labels{/name}","comments_url":"https://api.github.com/repos/skypjack/entt/issues/152/comments","events_url":"https://api.github.com/repos/skypjack/entt/issues/152/events","html_url":"https://github.com/skypjack/entt/issues/152","id":379582902,"node_id":"MDU6SXNzdWUzNzk1ODI5MDI=","number":152,"title":"Express the mutability of components in the template parameters of a view","user":{"login":"Kerndog73","id":10371177,"node_id":"MDQ6VXNlcjEwMzcxMTc3","avatar_url":"https://avatars3.githubusercontent.com/u/10371177?v=4","gravatar_id":"","url":"https://api.github.com/users/Kerndog73","html_url":"https://github.com/Kerndog73","followers_url":"https://api.github.com/users/Kerndog73/followers","following_url":"https://api.github.com/users/Kerndog73/following{/other_user}","gists_url":"https://api.github.com/users/Kerndog73/gists{/gist_id}","starred_url":"https://api.github.com/users/Kerndog73/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kerndog73/subscriptions","organizations_url":"https://api.github.com/users/Kerndog73/orgs","repos_url":"https://api.github.com/users/Kerndog73/repos","events_url":"https://api.github.com/users/Kerndog73/events{/privacy}","received_events_url":"https://api.github.com/users/Kerndog73/received_events","type":"User","site_admin":false},"labels":[{"id":570245204,"node_id":"MDU6TGFiZWw1NzAyNDUyMDQ=","url":"https://api.github.com/repos/skypjack/entt/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":{"login":"skypjack","id":1812216,"node_id":"MDQ6VXNlcjE4MTIyMTY=","avatar_url":"https://avatars1.githubusercontent.com/u/1812216?v=4","gravatar_id":"","url":"https://api.github.com/users/skypjack","html_url":"https://github.com/skypjack","followers_url":"https://api.github.com/users/skypjack/followers","following_url":"https://api.github.com/users/skypjack/following{/other_user}","gists_url":"https://api.github.com/users/skypjack/gists{/gist_id}","starred_url":"https://api.github.com/users/skypjack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skypjack/subscriptions","organizations_url":"https://api.github.com/users/skypjack/orgs","repos_url":"https://api.github.com/users/skypjack/repos","events_url":"https://api.github.com/users/skypjack/events{/privacy}","received_events_url":"https://api.github.com/users/skypjack/received_events","type":"User","site_admin":false},"assignees":[{"login":"skypjack","id":1812216,"node_id":"MDQ6VXNlcjE4MTIyMTY=","avatar_url":"https://avatars1.githubusercontent.com/u/1812216?v=4","gravatar_id":"","url":"https://api.github.com/users/skypjack","html_url":"https://github.com/skypjack","followers_url":"https://api.github.com/users/skypjack/followers","following_url":"https://api.github.com/users/skypjack/following{/other_user}","gists_url":"https://api.github.com/users/skypjack/gists{/gist_id}","starred_url":"https://api.github.com/users/skypjack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skypjack/subscriptions","organizations_url":"https://api.github.com/users/skypjack/orgs","repos_url":"https://api.github.com/users/skypjack/repos","events_url":"https://api.github.com/users/skypjack/events{/privacy}","received_events_url":"https://api.github.com/users/skypjack/received_events","type":"User","site_admin":false}],"milestone":null,"comments":4,"created_at":"2018-11-12T00:39:12Z","updated_at":"2018-11-12T08:45:34Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"I thought I'd put this discussion in an issue so that it doesn't get lost in Gitter.\r\n\r\nThe problem with a `const` view not modifying components is that a copy of the `const` view can be made and the components can be modifyed with the copy. The fact that a `const` view cannot modify components really doesn't make much sense. A `const std::shared_ptr` can still be used to modify the stored object. A `const std::span` can still be used to modify the stored object.\r\n\r\nThe mutability (or const-ness as I like to call it) should be part of the template parameters of the view. This is similar to how `std::span` works. A `std::span<const int>` cannot be used to modify a sequence of integers but a `const std::span<int>` can.\r\n\r\nConsider this:\r\n\r\n```C++\r\n// The view object is const because we are not going to \"look at something else\"\r\nconst auto view = reg.view<const A, B>();\r\n// the type of the view is view<entity_type, const A, B>\r\nfor (const auto e : view) {\r\n  //       B &        =    const A &\r\n  view.get<B>(e).data = view.get<A>(e).data;\r\n}\r\n```\r\n\r\nComponents being looked at by a `const` view **can** be modified. The template parameters tell the view which components can be modified and which cannot. Knowing which components a system reads and writes is valuable information, especially when parallelism is involved. Declaring the mutability in the template parameters not only documents read/write components but also enforces that read-only components cannot be written. Notice from the example that `view.get<A>(e)` returns a `const A &` because `A` is declared as `const` in the template parameter.\r\n\r\nDetermining whether a component is declared `const` in the template parameters requires iterating the type list. This is what I came up with:\r\n\r\n```C++\r\ntemplate <typename Comp, typename... Comps>\r\nstruct find_comp;\r\n\r\ntemplate <typename Comp, typename... Tail>\r\nstruct find_comp<Comp, Comp, Tail...> {\r\n  using type = Comp;\r\n};\r\n\r\ntemplate <typename Comp, typename Head, typename... Tail>\r\nstruct find_comp<Comp, Head, Tail...> {\r\n  using type = std::conditional_t<\r\n    std::is_same_v<std::add_const_t<Comp>, Head>,\r\n    Head,\r\n    typename find_comp<Comp, Tail...>::type\r\n  >;\r\n};\r\n\r\ntemplate <typename Comp>\r\nstruct find_comp<Comp> {\r\n  using type = void;\r\n};\r\n\r\nstatic_assert(std::is_same_v<typename find_comp<int, int>::type, int>);\r\nstatic_assert(std::is_same_v<typename find_comp<int, const int>::type, const int>);\r\nstatic_assert(std::is_same_v<typename find_comp<int, char, short, int, long>::type, int>);\r\nstatic_assert(std::is_same_v<typename find_comp<int, char, short, const int, long>::type, const int>);\r\n```\r\n\r\nAfter fiddling around with the multi-component view for a while I managed to get this test to succeed.\r\n\r\n```C++\r\nauto view = reg.view<const int, long>();\r\nfor (const auto e : view) {\r\n  static_assert(std::is_same_v<const int &, decltype(view.get<int>(e))>);\r\n  static_assert(std::is_same_v<long &, decltype(view.get<long>(e))>);\r\n}\r\n```\r\n\r\nMy changes were rather sloppy which is why this is an issue and not a pull request. The modification to the view mostly consisted of putting `std::remove_const_t` in `pool_type` and `component_iterator_type`, then declaring this:\r\n\r\n```C++\r\ntemplate <typename Comp>\r\nusing ret_type = typename find_comp<Comp, Component...>::type;\r\n```\r\n\r\nand making `get` return `ret_type<Comp> &`. I also modified the registry by doing this:\r\n\r\n```C++\r\ntemplate<typename... Component>\r\nView<Entity, Component...> view() {\r\n    return View<Entity, Component...>{(\r\n        assure<std::remove_const_t<Component>>(), \r\n        pool<std::remove_const_t<Component>>()\r\n    )...};\r\n}\r\n```\r\n\r\nWhether or not a `const` registry should return views to `const` components is a separate discussion but I think it makes sense."},"comment":{"url":"https://api.github.com/repos/skypjack/entt/issues/comments/437800364","html_url":"https://github.com/skypjack/entt/issues/152#issuecomment-437800364","issue_url":"https://api.github.com/repos/skypjack/entt/issues/152","id":437800364,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNzgwMDM2NA==","user":{"login":"skypjack","id":1812216,"node_id":"MDQ6VXNlcjE4MTIyMTY=","avatar_url":"https://avatars1.githubusercontent.com/u/1812216?v=4","gravatar_id":"","url":"https://api.github.com/users/skypjack","html_url":"https://github.com/skypjack","followers_url":"https://api.github.com/users/skypjack/followers","following_url":"https://api.github.com/users/skypjack/following{/other_user}","gists_url":"https://api.github.com/users/skypjack/gists{/gist_id}","starred_url":"https://api.github.com/users/skypjack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skypjack/subscriptions","organizations_url":"https://api.github.com/users/skypjack/orgs","repos_url":"https://api.github.com/users/skypjack/repos","events_url":"https://api.github.com/users/skypjack/events{/privacy}","received_events_url":"https://api.github.com/users/skypjack/received_events","type":"User","site_admin":false},"created_at":"2018-11-12T08:45:34Z","updated_at":"2018-11-12T08:45:34Z","author_association":"OWNER","body":"At a first glance (keep in mind that I cannot work on it right now, so it's just a fast review of what we have) it doesn't make sense to create pools of const components nor to ask to the registry to _do things_ (for some definitions of _doing things_) with const components *BUT* it makes sense to create views that mix both const and non-const components. It's also something probably easier to do and to maintain as a convention.  \r\nWas this what you were looking for? It would allow us to create const views from the registry somehow, even though I've yet to realize how to proceed."}}
{"actor":{"display_login":"skypjack"}}