On May 4, 2013, at 2:56 AM, Vicente J. Botet Escriba
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