Right now, sentinel() casts the `basic_parser` pointer (`this`) to
`const char *`, but that pointer is not unique if the input buffer
happens to be placed right before the `basic_parser_impl` instance -
the end of that buffer then has the same address as `basic_parser`.
Example code:
```
struct {
char buffer[8]{"{\"12345\""};
boost::json::stream_parser p;
} s;
s.p.write(s.buffer, sizeof(s.buffer));
s.p.write(":0}", 3);
```
This stops parsing at the end of the buffer, and then the
`incomplete()` check in `parse_string()` will return true; the second
`write()` call will crash with assertion failure:
> boost/json/basic_parser_impl.hpp:1016: const char* boost::json::basic_parser<Handler>::parse_unescaped(const char*, std::integral_constant<bool, StackEmpty_>, std::integral_constant<bool, AllowComments_>, bool) [with bool StackEmpty_ = true; bool IsKey_ = true; Handler = boost::json::detail::handler]: Assertion `*cs == '\x22'' failed.
This changes `sentinel()` by adding 1 to guaranteed that the sentinel
pointer is unique even if the input buffers borders on this object.
* take advantage of mp11
* split container_traits into several traits and helpers
* split map_traits into several traits
* use value_type more consistently
* refactor detail::inserter
* use detail::inserter with map-like types
* refactor conversion of tuple-like to array
* require unique keys for ToMapLike types (without it multimaps don't
round-trip)
The reference/iterator invalidation rules can surprise people who expect
associative containers to be node-based, similar to `std::[unordered_]map`.
This calls it out more visibly to avoid surprises.