VS2013's std::vector does not support incomplete template types.

This commit works around this by exposing the zonelet class declaration
to the public tz.h header.
This commit is contained in:
Sascha Zelzer
2016-09-15 17:20:38 +02:00
committed by Howard Hinnant
parent 553affefa4
commit 641cd739c3
3 changed files with 73 additions and 50 deletions

82
tz.cpp
View File

@@ -202,6 +202,8 @@ namespace date
// | Begin Configuration | // | Begin Configuration |
// +---------------------+ // +---------------------+
using namespace detail;
static std::string get_install() static std::string get_install()
{ {
#ifdef _WIN32 #ifdef _WIN32
@@ -784,7 +786,7 @@ parse_signed_time(std::istream& in)
// MonthDayTime // MonthDayTime
MonthDayTime::MonthDayTime(local_seconds tp, tz timezone) detail::MonthDayTime::MonthDayTime(local_seconds tp, tz timezone)
: zone_(timezone) : zone_(timezone)
{ {
using namespace date; using namespace date;
@@ -797,14 +799,14 @@ MonthDayTime::MonthDayTime(local_seconds tp, tz timezone)
s_ = hms.seconds(); s_ = hms.seconds();
} }
MonthDayTime::MonthDayTime(const date::month_day& md, tz timezone) detail::MonthDayTime::MonthDayTime(const date::month_day& md, tz timezone)
: zone_(timezone) : zone_(timezone)
{ {
u = md; u = md;
} }
date::day date::day
MonthDayTime::day() const detail::MonthDayTime::day() const
{ {
switch (type_) switch (type_)
{ {
@@ -820,7 +822,7 @@ MonthDayTime::day() const
} }
date::month date::month
MonthDayTime::month() const detail::MonthDayTime::month() const
{ {
switch (type_) switch (type_)
{ {
@@ -836,7 +838,7 @@ MonthDayTime::month() const
} }
int int
MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx, detail::MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx,
std::chrono::seconds offset, std::chrono::minutes prev_save) const std::chrono::seconds offset, std::chrono::minutes prev_save) const
{ {
if (zone_ != x.zone_) if (zone_ != x.zone_)
@@ -878,7 +880,7 @@ MonthDayTime::compare(date::year y, const MonthDayTime& x, date::year yx,
} }
sys_seconds sys_seconds
MonthDayTime::to_sys(date::year y, std::chrono::seconds offset, detail::MonthDayTime::to_sys(date::year y, std::chrono::seconds offset,
std::chrono::seconds save) const std::chrono::seconds save) const
{ {
using namespace date; using namespace date;
@@ -891,29 +893,29 @@ MonthDayTime::to_sys(date::year y, std::chrono::seconds offset,
return until_utc; return until_utc;
} }
MonthDayTime::U& detail::MonthDayTime::U&
MonthDayTime::U::operator=(const date::month_day& x) detail::MonthDayTime::U::operator=(const date::month_day& x)
{ {
month_day_ = x; month_day_ = x;
return *this; return *this;
} }
MonthDayTime::U& detail::MonthDayTime::U&
MonthDayTime::U::operator=(const date::month_weekday_last& x) detail::MonthDayTime::U::operator=(const date::month_weekday_last& x)
{ {
month_weekday_last_ = x; month_weekday_last_ = x;
return *this; return *this;
} }
MonthDayTime::U& detail::MonthDayTime::U&
MonthDayTime::U::operator=(const pair& x) detail::MonthDayTime::U::operator=(const pair& x)
{ {
month_day_weekday_ = x; month_day_weekday_ = x;
return *this; return *this;
} }
date::sys_days date::sys_days
MonthDayTime::to_sys_days(date::year y) const detail::MonthDayTime::to_sys_days(date::year y) const
{ {
using namespace std::chrono; using namespace std::chrono;
using namespace date; using namespace date;
@@ -940,14 +942,14 @@ MonthDayTime::to_sys_days(date::year y) const
} }
sys_seconds sys_seconds
MonthDayTime::to_time_point(date::year y) const detail::MonthDayTime::to_time_point(date::year y) const
{ {
// Add seconds first to promote to largest rep early to prevent overflow // Add seconds first to promote to largest rep early to prevent overflow
return to_sys_days(y) + s_ + h_ + m_; return to_sys_days(y) + s_ + h_ + m_;
} }
void void
MonthDayTime::canonicalize(date::year y) detail::MonthDayTime::canonicalize(date::year y)
{ {
using namespace std::chrono; using namespace std::chrono;
using namespace date; using namespace date;
@@ -986,7 +988,7 @@ MonthDayTime::canonicalize(date::year y)
} }
std::istream& std::istream&
operator>>(std::istream& is, MonthDayTime& x) detail::operator>>(std::istream& is, MonthDayTime& x)
{ {
using namespace date; using namespace date;
using namespace std::chrono; using namespace std::chrono;
@@ -1078,7 +1080,7 @@ operator>>(std::istream& is, MonthDayTime& x)
} }
std::ostream& std::ostream&
operator<<(std::ostream& os, const MonthDayTime& x) detail::operator<<(std::ostream& os, const MonthDayTime& x)
{ {
switch (x.type_) switch (x.type_)
{ {
@@ -1118,7 +1120,7 @@ operator<<(std::ostream& os, const MonthDayTime& x)
// Rule // Rule
Rule::Rule(const std::string& s) detail::Rule::Rule(const std::string& s)
{ {
try try
{ {
@@ -1182,7 +1184,7 @@ Rule::Rule(const std::string& s)
} }
} }
Rule::Rule(const Rule& r, date::year starting_year, date::year ending_year) detail::Rule::Rule(const Rule& r, date::year starting_year, date::year ending_year)
: name_(r.name_) : name_(r.name_)
, starting_year_(starting_year) , starting_year_(starting_year)
, ending_year_(ending_year) , ending_year_(ending_year)
@@ -1193,7 +1195,7 @@ Rule::Rule(const Rule& r, date::year starting_year, date::year ending_year)
} }
bool bool
operator==(const Rule& x, const Rule& y) detail::operator==(const Rule& x, const Rule& y)
{ {
if (std::tie(x.name_, x.save_, x.starting_year_, x.ending_year_) == if (std::tie(x.name_, x.save_, x.starting_year_, x.ending_year_) ==
std::tie(y.name_, y.save_, y.starting_year_, y.ending_year_)) std::tie(y.name_, y.save_, y.starting_year_, y.ending_year_))
@@ -1202,7 +1204,7 @@ operator==(const Rule& x, const Rule& y)
} }
bool bool
operator<(const Rule& x, const Rule& y) detail::operator<(const Rule& x, const Rule& y)
{ {
using namespace std::chrono; using namespace std::chrono;
auto const xm = x.month(); auto const xm = x.month();
@@ -1217,55 +1219,55 @@ operator<(const Rule& x, const Rule& y)
} }
bool bool
operator==(const Rule& x, const date::year& y) detail::operator==(const Rule& x, const date::year& y)
{ {
return x.starting_year_ <= y && y <= x.ending_year_; return x.starting_year_ <= y && y <= x.ending_year_;
} }
bool bool
operator<(const Rule& x, const date::year& y) detail::operator<(const Rule& x, const date::year& y)
{ {
return x.ending_year_ < y; return x.ending_year_ < y;
} }
bool bool
operator==(const date::year& x, const Rule& y) detail::operator==(const date::year& x, const Rule& y)
{ {
return y.starting_year_ <= x && x <= y.ending_year_; return y.starting_year_ <= x && x <= y.ending_year_;
} }
bool bool
operator<(const date::year& x, const Rule& y) detail::operator<(const date::year& x, const Rule& y)
{ {
return x < y.starting_year_; return x < y.starting_year_;
} }
bool bool
operator==(const Rule& x, const std::string& y) detail::operator==(const Rule& x, const std::string& y)
{ {
return x.name() == y; return x.name() == y;
} }
bool bool
operator<(const Rule& x, const std::string& y) detail::operator<(const Rule& x, const std::string& y)
{ {
return x.name() < y; return x.name() < y;
} }
bool bool
operator==(const std::string& x, const Rule& y) detail::operator==(const std::string& x, const Rule& y)
{ {
return y.name() == x; return y.name() == x;
} }
bool bool
operator<(const std::string& x, const Rule& y) detail::operator<(const std::string& x, const Rule& y)
{ {
return x < y.name(); return x < y.name();
} }
std::ostream& std::ostream&
operator<<(std::ostream& os, const Rule& r) detail::operator<<(std::ostream& os, const Rule& r)
{ {
using namespace date; using namespace date;
using namespace std::chrono; using namespace std::chrono;
@@ -1284,13 +1286,13 @@ operator<<(std::ostream& os, const Rule& r)
} }
date::day date::day
Rule::day() const detail::Rule::day() const
{ {
return starting_at_.day(); return starting_at_.day();
} }
date::month date::month
Rule::month() const detail::Rule::month() const
{ {
return starting_at_.month(); return starting_at_.month();
} }
@@ -1309,7 +1311,7 @@ struct find_rule_by_name
}; };
bool bool
Rule::overlaps(const Rule& x, const Rule& y) detail::Rule::overlaps(const Rule& x, const Rule& y)
{ {
// assume x.starting_year_ <= y.starting_year_; // assume x.starting_year_ <= y.starting_year_;
if (!(x.starting_year_ <= y.starting_year_)) if (!(x.starting_year_ <= y.starting_year_))
@@ -1324,7 +1326,7 @@ Rule::overlaps(const Rule& x, const Rule& y)
} }
void void
Rule::split(std::vector<Rule>& rules, std::size_t i, std::size_t k, std::size_t& e) detail::Rule::split(std::vector<Rule>& rules, std::size_t i, std::size_t k, std::size_t& e)
{ {
using namespace date; using namespace date;
using difference_type = std::vector<Rule>::iterator::difference_type; using difference_type = std::vector<Rule>::iterator::difference_type;
@@ -1393,7 +1395,7 @@ Rule::split(std::vector<Rule>& rules, std::size_t i, std::size_t k, std::size_t&
} }
void void
Rule::split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e) detail::Rule::split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e)
{ {
using difference_type = std::vector<Rule>::iterator::difference_type; using difference_type = std::vector<Rule>::iterator::difference_type;
auto j = i; auto j = i;
@@ -1417,7 +1419,7 @@ Rule::split_overlaps(std::vector<Rule>& rules, std::size_t i, std::size_t& e)
} }
void void
Rule::split_overlaps(std::vector<Rule>& rules) detail::Rule::split_overlaps(std::vector<Rule>& rules)
{ {
using difference_type = std::vector<Rule>::iterator::difference_type; using difference_type = std::vector<Rule>::iterator::difference_type;
for (std::size_t i = 0; i < rules.size();) for (std::size_t i = 0; i < rules.size();)
@@ -1456,7 +1458,7 @@ Rule::split_overlaps(std::vector<Rule>& rules)
// time_zone // time_zone
time_zone::zonelet::~zonelet() detail::zonelet::~zonelet()
{ {
#if !defined(_MSC_VER) || (_MSC_VER >= 1900) #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
using minutes = std::chrono::minutes; using minutes = std::chrono::minutes;
@@ -1468,14 +1470,14 @@ time_zone::zonelet::~zonelet()
#endif #endif
} }
time_zone::zonelet::zonelet() detail::zonelet::zonelet()
{ {
#if !defined(_MSC_VER) || (_MSC_VER >= 1900) #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
::new(&u.rule_) std::string(); ::new(&u.rule_) std::string();
#endif #endif
} }
time_zone::zonelet::zonelet(const zonelet& i) detail::zonelet::zonelet(const zonelet& i)
: gmtoff_(i.gmtoff_) : gmtoff_(i.gmtoff_)
, tag_(i.tag_) , tag_(i.tag_)
, format_(i.format_) , format_(i.format_)
@@ -2108,7 +2110,7 @@ operator<<(std::ostream& os, const time_zone& z)
os << ' '; os << ' ';
os << make_time(s.gmtoff_) << " "; os << make_time(s.gmtoff_) << " ";
os.width(15); os.width(15);
if (s.tag_ != time_zone::zonelet::has_save) if (s.tag_ != zonelet::has_save)
os << s.u.rule_; os << s.u.rule_;
else else
{ {

25
tz.h
View File

@@ -75,6 +75,10 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true,
#include "date.h" #include "date.h"
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#include "tz_private.h"
#endif
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
@@ -197,7 +201,7 @@ ambiguous_local_time::make_msg(local_time<Duration> tp,
return os.str(); return os.str();
} }
class Rule; namespace detail { class Rule; }
struct sys_info struct sys_info
{ {
@@ -299,13 +303,16 @@ operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y)
return !(x == y); return !(x == y);
} }
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
namespace detail { struct zonelet; }
#endif
class time_zone class time_zone
{ {
private: private:
struct zonelet;
std::string name_; std::string name_;
std::vector<zonelet> zonelets_; std::vector<detail::zonelet> zonelets_;
#if LAZY_INIT #if LAZY_INIT
std::unique_ptr<std::once_flag> adjusted_; std::unique_ptr<std::once_flag> adjusted_;
#endif #endif
@@ -343,7 +350,7 @@ public:
friend std::ostream& operator<<(std::ostream& os, const time_zone& z); friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
void add(const std::string& s); void add(const std::string& s);
void adjust_infos(const std::vector<Rule>& rules); void adjust_infos(const std::vector<detail::Rule>& rules);
private: private:
sys_info get_info_impl(sys_seconds tp) const; sys_info get_info_impl(sys_seconds tp) const;
@@ -673,11 +680,11 @@ struct timezone_info
struct TZ_DB struct TZ_DB
{ {
std::string version; std::string version;
std::vector<time_zone> zones; std::vector<time_zone> zones;
std::vector<link> links; std::vector<link> links;
std::vector<leap> leaps; std::vector<leap> leaps;
std::vector<Rule> rules; std::vector<detail::Rule> rules;
#ifdef TIMEZONE_MAPPING #ifdef TIMEZONE_MAPPING
// TODO! These need some protection. // TODO! These need some protection.
std::vector<detail::timezone_mapping> mappings; std::vector<detail::timezone_mapping> mappings;

View File

@@ -27,11 +27,19 @@
// been invented (that woud involve another several millennia of evolution). // been invented (that woud involve another several millennia of evolution).
// We did not mean to shout. // We did not mean to shout.
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
#include "tz.h" #include "tz.h"
#else
#include "date.h"
#include <vector>
#endif
namespace date namespace date
{ {
namespace detail
{
enum class tz {utc, local, standard}; enum class tz {utc, local, standard};
class MonthDayTime class MonthDayTime
@@ -187,7 +195,7 @@ inline bool operator> (const std::string& x, const Rule& y) {return y < x;}
inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);} inline bool operator<=(const std::string& x, const Rule& y) {return !(y < x);}
inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);} inline bool operator>=(const std::string& x, const Rule& y) {return !(x < y);}
struct time_zone::zonelet struct zonelet
{ {
enum tag {has_rule, has_save, is_empty}; enum tag {has_rule, has_save, is_empty};
@@ -226,6 +234,12 @@ struct time_zone::zonelet
zonelet& operator=(const zonelet&) = delete; zonelet& operator=(const zonelet&) = delete;
}; };
} // namespace detail
} // namespace date } // namespace date
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#include "tz.h"
#endif
#endif // TZ_PRIVATE_H #endif // TZ_PRIVATE_H