Boost logo

Boost :

Subject: Re: [boost] [gsoc 2013] draft proposal for chrono::date
From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2013-05-04 11:26:08


On May 4, 2013, at 2:56 AM, Vicente J. Botet Escriba <vicente.botet_at_[hidden]> wrote:

> Just to be sure I'm not trying to solve an issue that doesn't needs to be solved:
> Given
>
> date d = day(33) / month(5) / 2013;
>
> Note that I has a typo on the day. This is equivalent on my implementation to
>
> date d(year(2013), month(5), day(33));
>
> If I want to throw a bad date exception I would need to check that the day/month and year are in range. Next follows the code:
>
> days_date::days_date(year y, month m, day d)
> {
> if (set_if_valid_date(y, m, d))
> return;
> throw bad_date("day " + to_string(d) + " is out of range for "
> + to_string(y) + '-' + to_string(m));
> }
>
> bool days_date::set_if_valid_date(year y, month m, day d) noexcept
> {
> // [0]
> bool leap = is_leap(y.value()); // [1]
> const day_of_year::rep* year_data = days_in_year_before(leap);
>
> if (!(d.value() <= year_data[m.value()] - year_data[m.value()-1])) // [2]
> {
> return false;
> }
> year::rep by = y.value() + 32799; // [3]
> x_ = days_before_year(by) + year_data[m.value()-1] + d.value(); // [4]
> return true;
> }
>
> [1] and [3] presumes the year is in range.
> [2] and [4] presumes the day and month are in range.
>
> If some of 3 values are not in range the function set_if_valid_date could return true or false arbitrarily.
> So if the day/month and year are just names and don't ensure range I would need to start by validating their range in [0] so that if some of them is out of range the function return false;
>
> This mean that the user is not able, using the type system, to help the implementation to reduce needed check.
> I have no measures of the impact of these 3 range checks (6 comparisons).
> I just wanted to avoid them.
>
> Even if we use other kind of cache, I don't see how the cached data can be accessed without checking the range are correct.
>
> E.g. An alternative implementation using a cache for the year_month_cache
>
> bool days_date::set_if_valid_date(year y, month m, day d) noexcept
> {
> // [0]
> auto c = year_month_cache(y, m); // [1]
> if (d.value() >= c.days_in_month) return false;
> x_ = c.days_before + d.value(); // [2]
> return true;
> }
>
> This needs that y and m anre in range at [1] and d in in range at [2].
>
> Howard, could you tell me if you find something wrong on my analysis?
> I want to be too purist?

I think I see the disconnect. Simplifying as much as possible (hopefully not too much), you prefer:

   days_date(year::rep, month::rep, day::rep, no_check_t);

whereas I prefer for the same functionality:

   days_date(year, month, day);

or for the sake of removing part of the debate:

   days_date(year, month, day, no_check_t);

Your design doesn't require that year, month and day objects be "validation free", but mine does. And then I'm also seeing constructors like this running around (which I also experimented with):

    month::month(int m, no_check_t);

Exploring design decisions like these would make a pretty good topic for a gsoc. :-)

Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk