These `tag_invoke` overloads take an extra `as_string` parameter, which disambiguates this specific representation of `ip_address` from all other potential representations. In order to take advantage of them one needs to pass an `as_string` object to <<ref_value_from>> or <<ref_value_to>> as the last argument:
Often it is needed to use several conversion contexts together. For example, consider a log of remote users identified by IP addresses accessing a system. We can represent it as `std::vector<std::pair<std::chrono::system_clock::time_point, ip_address>>`. We want to serialize both ``ip_address``es and ``time_point``s as strings, but for this we need both `as_string` and `as_iso_8601` contexts. To combine several contexts just use {std_tuple}. Conversion functions will select the first element of the tuple for which a `tag_invoke` overload exists and will call that overload. As usual, `tag_invoke` overloads that don't use contexts and library-provided generic conversions are also supported. Thus, here's our example: