[PATCH] libstdc++: Fix operator overload resolution for calendar types

Patrick Palka ppalka@redhat.com
Tue Aug 25 19:51:38 GMT 2020


On Tue, 25 Aug 2020, Patrick Palka wrote:

> My original patch that implemented the calendar type operations failed
> to enforce a constraint on some of the addition/subtraction operator
> overloads that take a 'months' argument:
> 
>   Constraints: If the argument supplied by the caller for the months
>   parameter is convertible to years, its implicit conversion sequence to
>   years is worse than its implicit conversion sequence to months
> 
> This constraint is relevant when adding/subtracting a duration to/from
> say a year_month when the given duration is convertible to both 'months'
> and to 'years'.  The correct behavior here in light of this constraint
> is to select the (more efficient) 'years'-taking overload, but we
> currently emit an ambiguous overload error.
> 
> This patch follows the approach taken in the 'date' library and defines
> the constrained 'months'-taking operator overloads as function
> templates, so that we break such a implicit-conversion tie by selecting
> the non-template 'years'-taking overload.
> 
> Tested on x86_64-pc-linux-gnu, does this look OK to commit?  (The below
> diff is generated with --ignore-space-change for easier review.  In the
> actual patch, the function templates are indented two extra spaces after
> the template parameter list.)
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/chrono (__detail::__unspecified_month_disambuator):
> 	Define.

Whoops, this ChangeLog line should say
__detail::__months_years_conversion_disambiguator.

> 	(year_month::operator+=): Turn the 'months'-taking overload
> 	into a function template, so that the 'years'-taking overload is
> 	selected in case of an equally-ranked implicit conversion
> 	sequence to both 'months' and 'years' from the supplied argument.
> 	(year_month::operator-=): Likewise.
> 	(year_month::operator+): Likewise.
> 	(year_month::operator-): Likewise.
> 	(year_month_day::operator+=): Likewise.
> 	(year_month_day::operator-=): Likewise.
> 	(year_month_day::operator+): Likewise.
> 	(year_month_day::operator-): Likewise.
> 	(year_month_day_last::operator+=): Likewise.
> 	(year_month_day_last::operator-=): Likewise.
> 	(year_month_day_last::operator+): Likewise
> 	(year_month_day_last::operator-): Likewise.
> 	(year_month_day_weekday::operator+=): Likewise
> 	(year_month_day_weekday::operator-=): Likewise.
> 	(year_month_day_weekday::operator+): Likewise.
> 	(year_month_day_weekday::operator-): Likewise.
> 	(year_month_day_weekday_last::operator+=): Likewise
> 	(year_month_day_weekday_last::operator-=): Likewise.
> 	(year_month_day_weekday_last::operator+): Likewise.
> 	(year_month_day_weekday_last::operator-): Likewise.
> 	(testsuite/std/time/year_month/2.cc): New test.
> 	(testsuite/std/time/year_month_day/2.cc): New test.
> 	(testsuite/std/time/year_month_day_last/2.cc): New test.
> 	(testsuite/std/time/year_month_weekday/2.cc): New test.
> 	(testsuite/std/time/year_month_weekday_last/2.cc): New test.
> ---
>  libstdc++-v3/include/std/chrono               | 52 ++++++++++++++++++-
>  .../testsuite/std/time/year_month/2.cc        | 40 ++++++++++++++
>  .../testsuite/std/time/year_month_day/2.cc    | 40 ++++++++++++++
>  .../std/time/year_month_day_last/2.cc         | 40 ++++++++++++++
>  .../std/time/year_month_weekday/2.cc          | 40 ++++++++++++++
>  .../std/time/year_month_weekday_last/2.cc     | 40 ++++++++++++++
>  6 files changed, 250 insertions(+), 2 deletions(-)
>  create mode 100644 libstdc++-v3/testsuite/std/time/year_month/2.cc
>  create mode 100644 libstdc++-v3/testsuite/std/time/year_month_day/2.cc
>  create mode 100644 libstdc++-v3/testsuite/std/time/year_month_day_last/2.cc
>  create mode 100644 libstdc++-v3/testsuite/std/time/year_month_weekday/2.cc
>  create mode 100644 libstdc++-v3/testsuite/std/time/year_month_weekday_last/2.cc
> 
> diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
> index 3cc1438a7b6..0e272c3da58 100644
> --- a/libstdc++-v3/include/std/chrono
> +++ b/libstdc++-v3/include/std/chrono
> @@ -2046,6 +2046,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  
>      // YEAR_MONTH
>  
> +    namespace __detail
> +    {
> +      // [time.cal.ym], [time.cal.ymd], etc constrain the 'months'-taking
> +      // addition/subtraction operator overloads like so:
> +      //
> +      //   Constraints: if the argument supplied by the caller for the months
> +      //   parameter is convertible to years, its implicit conversion sequence
> +      //   to years is worse than its implicit conversion sequence to months.
> +      //
> +      // We realize this constraint by defining the 'months'-taking overloads as
> +      // function templates (with a dummy defaulted template parameter), so that
> +      // overload resolution doesn't select the 'months'-taking overload unless
> +      // the implicit conversion sequence to 'months' is better than that to
> +      // 'years'.
> +      using __months_years_conversion_disambiguator = void;
> +    }
> +
>      class year_month
>      {
>      private:
> @@ -2068,6 +2085,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        month() const noexcept
>        { return _M_m; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month&
>  	operator+=(const months& __dm) noexcept
>  	{
> @@ -2075,6 +2093,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return *this;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month&
>  	operator-=(const months& __dm) noexcept
>  	{
> @@ -2108,6 +2127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        operator<=>(const year_month& __x, const year_month& __y) noexcept
>  	= default;
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month
>  	operator+(const year_month& __ym, const months& __dm) noexcept
>  	{
> @@ -2120,10 +2140,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return __y / __m;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month
>  	operator+(const months& __dm, const year_month& __ym) noexcept
>  	{ return __ym + __dm; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month
>  	operator-(const year_month& __ym, const months& __dm) noexcept
>  	{ return __ym + -__dm; }
> @@ -2200,6 +2222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        : year_month_day(sys_days{__dp.time_since_epoch()})
>        { }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_day&
>  	operator+=(const months& __m) noexcept
>  	{
> @@ -2207,6 +2230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return *this;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_day&
>  	operator-=(const months& __m) noexcept
>  	{
> @@ -2262,10 +2286,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        operator<=>(const year_month_day& __x, const year_month_day& __y) noexcept
>  	= default;
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day
>  	operator+(const year_month_day& __ymd, const months& __dm) noexcept
>  	{ return (__ymd.year() / __ymd.month() + __dm) / __ymd.day(); }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day
>  	operator+(const months& __dm, const year_month_day& __ymd) noexcept
>  	{ return __ymd + __dm; }
> @@ -2278,6 +2304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        operator+(const years& __dy, const year_month_day& __ymd) noexcept
>        { return __ymd + __dy; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day
>  	operator-(const year_month_day& __ymd, const months& __dm) noexcept
>  	{ return __ymd + -__dm; }
> @@ -2364,6 +2391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        : _M_y{__y}, _M_mdl{__mdl}
>        { }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_day_last&
>  	operator+=(const months& __m) noexcept
>  	{
> @@ -2371,6 +2399,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return *this;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_day_last&
>  	operator-=(const months& __m) noexcept
>  	{
> @@ -2438,16 +2467,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  		  const year_month_day_last& __y) noexcept
>  	= default;
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day_last
>  	operator+(const year_month_day_last& __ymdl,
>  		  const months& __dm) noexcept
>  	{ return (__ymdl.year() / __ymdl.month() + __dm) / last; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day_last
>  	operator+(const months& __dm,
>  		  const year_month_day_last& __ymdl) noexcept
>  	{ return __ymdl + __dm; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_day_last
>  	operator-(const year_month_day_last& __ymdl,
>  		  const months& __dm) noexcept
> @@ -2544,6 +2576,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        : year_month_weekday{sys_days{__dp.time_since_epoch()}}
>        { }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_weekday&
>  	operator+=(const months& __m) noexcept
>  	{
> @@ -2551,6 +2584,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return *this;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_weekday&
>  	operator-=(const months& __m) noexcept
>  	{
> @@ -2626,10 +2660,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  && __x.weekday() == __y.weekday();
>        }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday
>  	operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept
> -      { return (__ymwd.year() / __ymwd.month() + __dm) / __ymwd.weekday_indexed(); }
> +	{
> +	  return ((__ymwd.year() / __ymwd.month() + __dm)
> +		  / __ymwd.weekday_indexed());
> +	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday
>  	operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept
>  	{ return __ymwd + __dm; }
> @@ -2642,6 +2681,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept
>        { return __ymwd + __dy; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday
>  	operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept
>  	{ return __ymwd + -__dm; }
> @@ -2690,6 +2730,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        : _M_y{__y}, _M_m{__m}, _M_wdl{__wdl}
>        { }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_weekday_last&
>  	operator+=(const months& __m) noexcept
>  	{
> @@ -2697,6 +2738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  return *this;
>  	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	constexpr year_month_weekday_last&
>  	operator-=(const months& __m) noexcept
>  	{
> @@ -2759,11 +2801,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	  && __x.weekday_last() == __y.weekday_last();
>        }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday_last
>  	operator+(const year_month_weekday_last& __ymwdl,
>  		  const months& __dm) noexcept
> -      { return (__ymwdl.year() / __ymwdl.month() + __dm) / __ymwdl.weekday_last(); }
> +	{
> +	  return ((__ymwdl.year() / __ymwdl.month() + __dm)
> +		  / __ymwdl.weekday_last());
> +	}
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday_last
>  	operator+(const months& __dm,
>  		  const year_month_weekday_last& __ymwdl) noexcept
> @@ -2779,6 +2826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  		const year_month_weekday_last& __ymwdl) noexcept
>        { return __ymwdl + __dy; }
>  
> +      template<typename = __detail::__months_years_conversion_disambiguator>
>  	friend constexpr year_month_weekday_last
>  	operator-(const year_month_weekday_last& __ymwdl,
>  		  const months& __dm) noexcept
> diff --git a/libstdc++-v3/testsuite/std/time/year_month/2.cc b/libstdc++-v3/testsuite/std/time/year_month/2.cc
> new file mode 100644
> index 00000000000..36e14667547
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/year_month/2.cc
> @@ -0,0 +1,40 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do compile { target c++2a } }
> +
> +// Copyright (C) 2020 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +// Class template year_month [time.cal.year_month]
> +
> +#include <chrono>
> +
> +constexpr void
> +constexpr_year_month_op_overload_disambiguation()
> +{
> +  using namespace std::chrono;
> +  using decades = duration<long long, std::ratio<31556952 * 10>>;
> +  static_assert(std::convertible_to<decades, months>
> +		&& std::convertible_to<decades, years>);
> +  using ym = year_month;
> +
> +  constexpr ym ym1 = 2015y/June;
> +  static_assert(ym1 + decades{1} == 2025y/June);
> +  static_assert(ym1 - decades{1} == 2005y/June);
> +  static_assert(decades{1} + ym1 == 2025y/June);
> +  static_assert((ym{ym1} += decades{1}) == 2025y/June);
> +  static_assert((ym{ym1} -= decades{1}) == 2005y/June);
> +}
> diff --git a/libstdc++-v3/testsuite/std/time/year_month_day/2.cc b/libstdc++-v3/testsuite/std/time/year_month_day/2.cc
> new file mode 100644
> index 00000000000..80d1f033c1d
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/year_month_day/2.cc
> @@ -0,0 +1,40 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do compile { target c++2a } }
> +
> +// Copyright (C) 2020 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +// Class template year_month_day [time.cal.year_month_day]
> +
> +#include <chrono>
> +
> +constexpr void
> +constexpr_year_month_day_op_overload_disambiguation()
> +{
> +  using namespace std::chrono;
> +  using decades = duration<long long, std::ratio<31556952 * 10>>;
> +  static_assert(std::convertible_to<decades, months>
> +		&& std::convertible_to<decades, years>);
> +  using ymd = year_month_day;
> +
> +  constexpr ymd ymd1 = 2015y/June/15d;
> +  static_assert(ymd1 + decades{1} == 2025y/June/15d);
> +  static_assert(ymd1 - decades{1} == 2005y/June/15d);
> +  static_assert(decades{1} + ymd1 == 2025y/June/15d);
> +  static_assert((ymd{ymd1} += decades{1}) == 2025y/June/15d);
> +  static_assert((ymd{ymd1} -= decades{1}) == 2005y/June/15d);
> +}
> diff --git a/libstdc++-v3/testsuite/std/time/year_month_day_last/2.cc b/libstdc++-v3/testsuite/std/time/year_month_day_last/2.cc
> new file mode 100644
> index 00000000000..dadbd3c38b5
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/year_month_day_last/2.cc
> @@ -0,0 +1,40 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do compile { target c++2a } }
> +
> +// Copyright (C) 2020 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +// Class template year_month_day_last [time.cal.year_month_day_last]
> +
> +#include <chrono>
> +
> +constexpr void
> +constexpr_year_month_day_last_op_overload_disambiguation()
> +{
> +  using namespace std::chrono;
> +  using decades = duration<long long, std::ratio<31556952 * 10>>;
> +  static_assert(std::convertible_to<decades, months>
> +		&& std::convertible_to<decades, years>);
> +  using ymdl = year_month_day_last;
> +
> +  constexpr ymdl ymdl1 = 2015y/June/last;
> +  static_assert(ymdl1 + decades{1} == 2025y/June/last);
> +  static_assert(ymdl1 - decades{1} == 2005y/June/last);
> +  static_assert(decades{1} + ymdl1 == 2025y/June/last);
> +  static_assert((ymdl{ymdl1} += decades{1}) == 2025y/June/last);
> +  static_assert((ymdl{ymdl1} -= decades{1}) == 2005y/June/last);
> +}
> diff --git a/libstdc++-v3/testsuite/std/time/year_month_weekday/2.cc b/libstdc++-v3/testsuite/std/time/year_month_weekday/2.cc
> new file mode 100644
> index 00000000000..6ddfb15b283
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/year_month_weekday/2.cc
> @@ -0,0 +1,40 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do compile { target c++2a } }
> +
> +// Copyright (C) 2020 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +// Class template year_month_weekday [time.cal.year_month_weekday]
> +
> +#include <chrono>
> +
> +constexpr void
> +constexpr_year_month_weekday_op_overload_disambiguation()
> +{
> +  using namespace std::chrono;
> +  using decades = duration<long long, std::ratio<31556952 * 10>>;
> +  static_assert(std::convertible_to<decades, months>
> +		&& std::convertible_to<decades, years>);
> +  using ymwd = year_month_weekday;
> +
> +  constexpr ymwd ymwd1 = 2015y/June/Monday[3];
> +  static_assert(ymwd1 + decades{1} == 2025y/June/Monday[3]);
> +  static_assert(ymwd1 - decades{1} == 2005y/June/Monday[3]);
> +  static_assert(decades{1} + ymwd1 == 2025y/June/Monday[3]);
> +  static_assert((ymwd{ymwd1} += decades{1}) == 2025y/June/Monday[3]);
> +  static_assert((ymwd{ymwd1} -= decades{1}) == 2005y/June/Monday[3]);
> +}
> diff --git a/libstdc++-v3/testsuite/std/time/year_month_weekday_last/2.cc b/libstdc++-v3/testsuite/std/time/year_month_weekday_last/2.cc
> new file mode 100644
> index 00000000000..170b5a45ad6
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/time/year_month_weekday_last/2.cc
> @@ -0,0 +1,40 @@
> +// { dg-options "-std=gnu++2a" }
> +// { dg-do compile { target c++2a } }
> +
> +// Copyright (C) 2020 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYING3.  If not see
> +// <http://www.gnu.org/licenses/>.
> +
> +// Class template year_month_weekday_last [time.cal.year_month_weekday_last]
> +
> +#include <chrono>
> +
> +constexpr void
> +constexpr_year_month_weekday_last_op_overload_disambiguation()
> +{
> +  using namespace std::chrono;
> +  using decades = duration<long long, std::ratio<31556952 * 10>>;
> +  static_assert(std::convertible_to<decades, months>
> +		&& std::convertible_to<decades, years>);
> +  using ymwdl = year_month_weekday_last;
> +
> +  constexpr ymwdl ymwdl1 = 2015y/June/Monday[last];
> +  static_assert(ymwdl1 + decades{1} == 2025y/June/Monday[last]);
> +  static_assert(ymwdl1 - decades{1} == 2005y/June/Monday[last]);
> +  static_assert(decades{1} + ymwdl1 == 2025y/June/Monday[last]);
> +  static_assert((ymwdl{ymwdl1} += decades{1}) == 2025y/June/Monday[last]);
> +  static_assert((ymwdl{ymwdl1} -= decades{1}) == 2005y/June/Monday[last]);
> +}
> -- 
> 2.28.0.337.ge9b77c84a0
> 
> 



More information about the Libstdc++ mailing list