Open michael-brade opened 1 year ago
Thanks for the self-contained test case! We talked about this at the weekly maintainer meeting; @dmitrykobets-msft noted that the C++ Standard doesn't recognize the existence of DLLs so this is technically not a conformance issue and we could simply decide that this is unsupported. @strega-nil-ms noted that zoned_time
is templated on TimeZonePtr
and that has relatively weak requirements. Because time_zone
itself stores only the name, I believe we could make this scenario work, while imposing relatively minimal runtime cost on non-DLL scenarios, and without impacting the compile-time correctness of custom TimeZonePtr
s, through the following approach:
if constexpr
the TimeZonePtr
is exactly const time_zone*
, then compare the pointed-to objects. (This handles the user DLL scenario. It does impose a runtime cost on non-DLL scenarios when the comparison resolves to false
, but the string
comparison should be fairly cheap and hopefully there aren't millions being performed every second.)Regarding test coverage, I would be satisfied with manual testing, without adding automated testing; we do have the ability to build multiple user binaries in our test harness but it's really obnoxious and I think it wouldn't be worth the effort here, as long as the relevant product code is commented as to why it's doing something beyond the Standard.
When the tzdb is updated, should zoned_times constructed from different versions of the tzdb be allowed to compare as equal?
The time_zone::operator== compares by name rather than by address. Since users cannot create time_zones, this means that time_zone from different versions of the tzdb can still be considered equal. I believe it makes sense to extend this property to zoned_time. Perhaps an LWG issue is needed here.
#include <chrono>
#include <cassert>
int main()
{
using namespace std::chrono;
auto&& tzdb = get_tzdb();
auto&& new_tzdb = reload_tzdb();
auto&& lzone = tzdb.current_zone();
auto&& new_lzone = new_tzdb.current_zone();
if (tzdb.version == new_tzdb.version)
return 1;
auto now = system_clock::now();
zoned_time lzt{ lzone, now };
zoned_time nlzt{ new_lzone, now };
assert(*lzone == *new_lzone);
// lzone == new_lzone ?
// lzt == nlzt ?
}
The time_zone::operator== compares by name rather than by address. Since users cannot create time_zones, this means that time_zone from different versions of the tzdb can still be considered equal.
I guess this is pointless at least for MSVC STL. MSVC STL's time_zone
only stores a string
which contains its name, and different time_zone
objects of the same name don't behave differently.
IMO, the return value for operator== for std::chrono::zoned_time which is stated in the standard as:
x.zone == y.zone && x.tp == y.tp
should instead be:
(x.zone_) == (y.zone) && x.tp == y.tp_
because it doesn't make sense to compare pointers. It should be comparing the data pointed to.
Pull request #3662 was supposed to fix this issue but it didn't supply the right test case. Here it is. The reason seems to be that
.get_time_zone()
returns a_TimeZonePtr
, so adresses of the pointers are compared instead of the actual data. If the time(zone) was created in a different DLL, then the addresses are not the same even if the time is exactly the same.Command-line test case
CMakeLists.txt
chrono-dll.cpp
chrono-test.cpp
Result:
Expected behavior
I expect to be able to compare zoned times even on different DLLs.
STL version