| 1 | // Copyright (c) 2020-2024 Antony Polukhin |
| 2 | // |
| 3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 5 | |
| 6 | #include <boost/core/lightweight_test.hpp> |
| 7 | |
| 8 | #include <boost/pfr/core.hpp> |
| 9 | |
| 10 | #include <chrono> |
| 11 | |
| 12 | #include <optional> |
| 13 | |
| 14 | // This class mimics libc++ implementation of std::chrono::duration with unfxed LWG3050 |
| 15 | template <class Rep, class Period> |
| 16 | class bogus_duration { |
| 17 | public: |
| 18 | bogus_duration() = default; |
| 19 | |
| 20 | template <class T> |
| 21 | explicit bogus_duration(const T& val, |
| 22 | typename std::enable_if< |
| 23 | std::is_convertible<T, Rep>::value // <= libstdc++ fix for LWG3050 is 's/T/const T&/g' |
| 24 | >::type* = nullptr) |
| 25 | : rep_(val) |
| 26 | {} |
| 27 | |
| 28 | template <class Rep2, class Period2> |
| 29 | bogus_duration(const bogus_duration<Rep2, Period2>& val, |
| 30 | typename std::enable_if<std::is_convertible<Period2, Rep>::value>::type* = nullptr) |
| 31 | : rep_(val) |
| 32 | {} |
| 33 | |
| 34 | Rep get_rep() const { return rep_; } |
| 35 | |
| 36 | private: |
| 37 | Rep rep_{0}; |
| 38 | }; |
| 39 | |
| 40 | struct struct_with_bogus_duration { |
| 41 | std::optional<bogus_duration<long, char>> d0; |
| 42 | std::optional<bogus_duration<long, char>> d1; |
| 43 | }; |
| 44 | |
| 45 | struct struct_with_optional { |
| 46 | std::optional<std::chrono::seconds> a; |
| 47 | std::optional<std::chrono::milliseconds> b; |
| 48 | std::optional<std::chrono::microseconds> c; |
| 49 | std::optional<std::chrono::nanoseconds> d; |
| 50 | std::optional<std::chrono::steady_clock::duration> e; |
| 51 | std::optional<std::chrono::system_clock::duration> f; |
| 52 | }; |
| 53 | |
| 54 | int main() { |
| 55 | struct_with_optional val{ |
| 56 | .a: std::chrono::seconds{1}, |
| 57 | .b: std::chrono::seconds{2}, |
| 58 | .c: std::chrono::seconds{3}, |
| 59 | .d: std::chrono::seconds{4}, |
| 60 | .e: std::chrono::seconds{5}, |
| 61 | .f: std::chrono::seconds{6}, |
| 62 | }; |
| 63 | |
| 64 | using boost::pfr::get; |
| 65 | BOOST_TEST(get<0>(val) == std::chrono::seconds{1}); |
| 66 | BOOST_TEST(get<1>(val) == std::chrono::seconds{2}); |
| 67 | BOOST_TEST(get<2>(val) == std::chrono::seconds{3}); |
| 68 | BOOST_TEST(get<3>(val) == std::chrono::seconds{4}); |
| 69 | BOOST_TEST(get<3>(val) > std::chrono::seconds{0}); |
| 70 | BOOST_TEST(get<3>(val) > std::chrono::seconds{0}); |
| 71 | |
| 72 | struct_with_bogus_duration val2{.d0: bogus_duration<long, char>{1}, .d1: bogus_duration<long, char>{2}}; |
| 73 | BOOST_TEST(get<0>(val2)->get_rep() == 1); |
| 74 | BOOST_TEST(get<1>(val2)->get_rep() == 2); |
| 75 | |
| 76 | return boost::report_errors(); |
| 77 | } |
| 78 | |
| 79 | |