[API BREAKING] Remove conversion from weekday to unsigned

* There has been a great deal of anguish over the encoding of
  weekdays:  whether [0, 6] maps to [Sunday, Saturday] or
  [1, 7] maps to [Monday, Sunday].  This commit attempts
  to address that issue, but will break a small amount of
  code at compile-time.  See below on how to fix that.

* The weekday constructor used to accept [0, 6] to represent
  [Sunday, Saturday].  It now accepts [0, 7] to represent
  [Sunday, Saturday] with both 0 and 7 mapping to Sunday.

* The conversion from weekday to unsigned has been removed.

* To convert a weekday to unsigned replace:

      auto u = unsigned{wd};

  with:

      auto u = (wd - Sunday).count();

  This maps [Sunday, Saturday] to [0, 6], which is the
  C/POSIX mapping.  If you prefer the ISO mapping
  ([Monday, Sunday] -> [1, 7]), then do:

      auto u = (wd - Monday).count() + 1;
This commit is contained in:
Howard Hinnant 2018-06-02 22:56:10 -04:00
parent 6c4d333026
commit 40b83654b6
4 changed files with 34 additions and 34 deletions

View File

@ -431,7 +431,6 @@ public:
CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
CONSTCD11 explicit operator unsigned() const NOEXCEPT;
CONSTCD11 bool ok() const NOEXCEPT;
CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
@ -439,6 +438,14 @@ public:
private:
static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT;
friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
template<class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
friend class weekday_indexed;
};
CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
@ -1765,7 +1772,7 @@ weekday::weekday_from_days(int z) NOEXCEPT
CONSTCD11
inline
weekday::weekday(unsigned wd) NOEXCEPT
: wd_(static_cast<decltype(wd_)>(wd))
: wd_(static_cast<decltype(wd_)>(wd != 7 ? wd : 0))
{}
CONSTCD11
@ -1803,13 +1810,6 @@ weekday::operator-=(const days& d) NOEXCEPT
return *this;
}
CONSTCD11
inline
weekday::operator unsigned() const NOEXCEPT
{
return static_cast<unsigned>(wd_);
}
CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
CONSTCD11
@ -1817,7 +1817,7 @@ inline
bool
operator==(const weekday& x, const weekday& y) NOEXCEPT
{
return static_cast<unsigned>(x) == static_cast<unsigned>(y);
return x.wd_ == y.wd_;
}
CONSTCD11
@ -1833,8 +1833,9 @@ inline
days
operator-(const weekday& x, const weekday& y) NOEXCEPT
{
auto const diff = static_cast<unsigned>(x) - static_cast<unsigned>(y);
return days{diff <= 6 ? diff : diff + 7};
auto const wdu = x.wd_ - y.wd_;
auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
return days{wdu - wk * 7};
}
CONSTCD14
@ -1842,7 +1843,7 @@ inline
weekday
operator+(const weekday& x, const days& y) NOEXCEPT
{
auto const wdu = static_cast<long long>(static_cast<unsigned>(x)) + y.count();
auto const wdu = static_cast<long long>(static_cast<unsigned>(x.wd_)) + y.count();
auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
return weekday{static_cast<unsigned>(wdu - wk * 7)};
}
@ -1874,7 +1875,7 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
os << format(fmt, wd);
}
else
os << static_cast<unsigned>(wd) << " is not a valid weekday";
os << static_cast<unsigned>(wd.wd_) << " is not a valid weekday";
return os;
}
@ -1939,13 +1940,13 @@ CONSTDATA date::month October{10};
CONSTDATA date::month November{11};
CONSTDATA date::month December{12};
CONSTDATA date::weekday Sunday{0u};
CONSTDATA date::weekday Monday{1u};
CONSTDATA date::weekday Tuesday{2u};
CONSTDATA date::weekday Wednesday{3u};
CONSTDATA date::weekday Thursday{4u};
CONSTDATA date::weekday Friday{5u};
CONSTDATA date::weekday Saturday{6u};
CONSTDATA date::weekday Monday{1};
CONSTDATA date::weekday Tuesday{2};
CONSTDATA date::weekday Wednesday{3};
CONSTDATA date::weekday Thursday{4};
CONSTDATA date::weekday Friday{5};
CONSTDATA date::weekday Saturday{6};
CONSTDATA date::weekday Sunday{7};
// weekday_indexed
@ -1975,7 +1976,7 @@ weekday_indexed::ok() const NOEXCEPT
CONSTCD11
inline
weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT
: wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd)))
: wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd.wd_)))
, index_(static_cast<decltype(index_)>(index))
{}
@ -4337,11 +4338,11 @@ extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& f
os.setstate(std::ios::failbit);
return 7;
}
unsigned wd;
weekday wd;
if (fds.ymd.ok())
{
wd = static_cast<unsigned>(weekday{fds.ymd});
if (fds.wd.ok() && wd != static_cast<unsigned>(fds.wd))
wd = weekday{fds.ymd};
if (fds.wd.ok() && wd != fds.wd)
{
// fds.ymd and fds.wd are inconsistent
os.setstate(std::ios::failbit);
@ -4349,8 +4350,8 @@ extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& f
}
}
else
wd = static_cast<unsigned>(fds.wd);
return wd;
wd = fds.wd;
return static_cast<unsigned>((wd - Sunday).count());
}
template <class CharT, class Traits, class Duration>
@ -7216,8 +7217,8 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
if (ymd.ok())
{
if (wd == not_a_weekday)
wd = static_cast<int>(static_cast<unsigned>(weekday(ymd)));
else if (wd != static_cast<int>(static_cast<unsigned>(weekday(ymd))))
wd = static_cast<int>((weekday(ymd) - Sunday).count());
else if (wd != static_cast<int>((weekday(ymd) - Sunday).count()))
goto broken;
if (!computed)
{

View File

@ -451,7 +451,7 @@ weekday::weekday(unsigned wd) NOEXCEPT
CONSTCD11
inline
weekday::weekday(date::weekday wd) NOEXCEPT
: wd_(to_iso_encoding(static_cast<unsigned>(wd)))
: wd_((wd-date::Monday).count() + 1)
{}
CONSTCD11

View File

@ -77,11 +77,9 @@ static_assert( std::is_trivially_move_assignable<date::weekday>{}, "");
static_assert( std::is_nothrow_constructible<date::weekday, unsigned>{}, "");
static_assert( std::is_nothrow_constructible<date::weekday, date::sys_days>{}, "");
static_assert( std::is_nothrow_constructible<unsigned, date::weekday>{}, "");
static_assert(!std::is_convertible<unsigned, date::weekday>{}, "");
static_assert( std::is_convertible<date::sys_days, date::weekday>{}, "");
static_assert(!std::is_convertible<date::weekday, unsigned>{}, "");
static_assert(static_cast<unsigned>(date::weekday{1u}) == 1, "");
static_assert( date::weekday{0u}.ok(), "");
static_assert( date::weekday{1u}.ok(), "");
@ -90,7 +88,8 @@ static_assert( date::weekday{3u}.ok(), "");
static_assert( date::weekday{4u}.ok(), "");
static_assert( date::weekday{5u}.ok(), "");
static_assert( date::weekday{6u}.ok(), "");
static_assert(!date::weekday{7u}.ok(), "");
static_assert( date::weekday{7u}.ok(), "");
static_assert(!date::weekday{8u}.ok(), "");
void
test_weekday_arithmetic()

View File

@ -171,7 +171,7 @@ test_with_date_weekday()
auto constexpr d1 = iso_week::sun;
static_assert(unsigned{d1} == 7, "");
auto constexpr d2 = date::weekday{d1};
static_assert(unsigned{d2} == 0, "");
static_assert(d2 == date::Sunday, "");
auto constexpr d3 = iso_week::weekday{d2};
static_assert(unsigned{d3} == 7, "");
}