{"action":"created","issue":{"url":"https://api.github.com/repos/cplusplus/networking-ts/issues/42","repository_url":"https://api.github.com/repos/cplusplus/networking-ts","labels_url":"https://api.github.com/repos/cplusplus/networking-ts/issues/42/labels{/name}","comments_url":"https://api.github.com/repos/cplusplus/networking-ts/issues/42/comments","events_url":"https://api.github.com/repos/cplusplus/networking-ts/issues/42/events","html_url":"https://github.com/cplusplus/networking-ts/issues/42","id":180684696,"number":42,"title":"Relax BidirectionalIterator requirements?","user":{"login":"vinniefalco","id":1503976,"avatar_url":"https://avatars.githubusercontent.com/u/1503976?v=3","gravatar_id":"","url":"https://api.github.com/users/vinniefalco","html_url":"https://github.com/vinniefalco","followers_url":"https://api.github.com/users/vinniefalco/followers","following_url":"https://api.github.com/users/vinniefalco/following{/other_user}","gists_url":"https://api.github.com/users/vinniefalco/gists{/gist_id}","starred_url":"https://api.github.com/users/vinniefalco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinniefalco/subscriptions","organizations_url":"https://api.github.com/users/vinniefalco/orgs","repos_url":"https://api.github.com/users/vinniefalco/repos","events_url":"https://api.github.com/users/vinniefalco/events{/privacy}","received_events_url":"https://api.github.com/users/vinniefalco/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-10-03T16:26:58Z","updated_at":"2016-10-03T20:11:39Z","closed_at":null,"body":"To put it simply, the C++ specification is deficient when it comes to defining iterator concepts, because it conflates the traversal and value access concerns. This is fully described here:\r\nhttp://www.boost.org/doc/libs/1_62_0/libs/iterator/doc/new-iter-concepts.html\r\n\r\nI propose that the networking proposal break new ground and push for addressing this defect. Specifically, for the **ConstBufferSequence** and **MutableBufferSequence** type requirements, replace the **BidirectionalIterator** requirement on `const_iterator` with the dual requirements **ReadableIterator** and **BidirectionalTraversalIterator**, defined here:\r\nhttp://www.boost.org/doc/libs/1_62_0/libs/iterator/doc/new-iter-concepts.html#readable-iterators-lib-readable-iterators\r\n\r\nRationale: This allows more flexible operations on buffer sequences, such as applying range transformations to the value type. Without this change, implementations that transform buffer sequences (such as concatenating them, adjusting the byte range they represent, or converting from mutable to const sequences) become overly complex, inefficient, or impossible.\r\n\r\nHere are examples of buffer sequence transformations in use today which would be disallowed by the current **BidirectionalIterator** requirements in the networking TS:\r\n\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/buffer_cat.hpp#L22\r\n\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/buffers_adapter.hpp#L17\r\n\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/consuming_buffers.hpp#L20\r\n\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/prepare_buffers.hpp#L135\r\n\r\nOne implementation above, `buffer_cat`, is particularly useful as it allows multiple system calls (to read or write on a socket) to be reduced to one. Consider a network protocol that sends objects which have multiple parts, such as a message header followed by a message body. The header and body could each be represented by a **ConstBufferSequence**. `buffer_cat` allows sending the entire message in a single system call instead of doing it in two separate calls. This has been used in the wild to achieve impressive decreases in latency for a HTTP server. The current implementation of `buffer_cat` is rather elegant, it uses the equivalent of a `std::variant` to efficiently transform the inputs without making a copy of the sequences:\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/detail/buffer_cat.hpp#L22\r\n\r\nThis implementation is unfortunately non conforming because the iterators it defines, do not meet the requirements of **BidirectionalIterator** since they return an rvalue:\r\nhttps://github.com/vinniefalco/Beast/blob/70b8555cdca69b9c5777db02115d30d1c1aad631/include/beast/core/detail/buffer_cat.hpp#L103\r\nThis was done because `buffer_cat` allows conversion from mutable sequences to const sequences. For example, if `a` and `b` are **ConstBufferSequence* objects, and `c` is a **MutableBufferSequence**, the expression `buffer_cat(a, b, c)` returns an object representing the concatenation of `a`, `b`, and `c`, whose type meets the requirements of **ConstBufferSequence**.\r\n\r\nThe alternative to the elegant, current implementation of `buffer_cat` is one that uses a `std::vector` equivalent to store a precomputed version of the concatenated sequence. Its true that a specialization could make this vector implementation required in only a subset of use cases but the solution is non-ideal.\r\n\r\nFor this reason, I urge the authors to consider requiring only **ReadableIterator** and **BidirectionalTraversalIterator** for iterators representing buffer sequences.\r\n"},"comment":{"url":"https://api.github.com/repos/cplusplus/networking-ts/issues/comments/251212801","html_url":"https://github.com/cplusplus/networking-ts/issues/42#issuecomment-251212801","issue_url":"https://api.github.com/repos/cplusplus/networking-ts/issues/42","id":251212801,"user":{"login":"vinniefalco","id":1503976,"avatar_url":"https://avatars.githubusercontent.com/u/1503976?v=3","gravatar_id":"","url":"https://api.github.com/users/vinniefalco","html_url":"https://github.com/vinniefalco","followers_url":"https://api.github.com/users/vinniefalco/followers","following_url":"https://api.github.com/users/vinniefalco/following{/other_user}","gists_url":"https://api.github.com/users/vinniefalco/gists{/gist_id}","starred_url":"https://api.github.com/users/vinniefalco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinniefalco/subscriptions","organizations_url":"https://api.github.com/users/vinniefalco/orgs","repos_url":"https://api.github.com/users/vinniefalco/repos","events_url":"https://api.github.com/users/vinniefalco/events{/privacy}","received_events_url":"https://api.github.com/users/vinniefalco/received_events","type":"User","site_admin":false},"created_at":"2016-10-03T20:11:39Z","updated_at":"2016-10-03T20:11:39Z","body":"I brought it up here\r\nhttps://github.com/ericniebler/range-v3/issues/479"}}
{"actor":{"display_login":"vinniefalco"}}