@@ -28,95 +28,111 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
2828namespace adaptor {
2929
3030namespace detail {
31- template <typename Target,
32- typename Source,
33- bool target_is_signed = std::is_signed<Target>::value,
34- bool source_is_signed = std::is_signed<Source>::value,
35- typename = typename std::enable_if<
36- std::is_integral<Target>::value &&
37- std::is_integral<Source>::value
38- >::type>
31+ template <
32+ typename Target,
33+ typename Source,
34+ bool target_is_signed = std::is_signed<Target>::value,
35+ bool source_is_signed = std::is_signed<Source>::value,
36+ typename = typename std::enable_if<
37+ std::is_integral<Target>::value &&
38+ std::is_integral<Source>::value
39+ >::type
40+ >
3941struct would_underflow {
40- // The default case includes the cases that Source being unsigned, and since Source
41- // is unsigned, no underflow can happen
42- would_underflow (Source) : value{false } {}
43- bool value;
42+ // The default case includes the cases that Source being unsigned, and since Source
43+ // is unsigned, no underflow can happen
44+ would_underflow (Source) : value{false } {}
45+ bool value;
4446};
4547
46- template <typename Target, typename Source>
48+ template <typename Target, typename Source>
4749struct would_underflow <Target, Source, false , true > {
48- // When Source is signed and Target is unsigned, we only need to compare with 0 to
49- // detect underflow, this works correctly and also avoids warnign from the compiler
50- would_underflow (Source source) : value{source < 0 } {}
51- bool value;
50+ // When Source is signed and Target is unsigned, we only need to compare with 0 to
51+ // detect underflow, this works correctly and also avoids warnings from the compiler
52+ would_underflow (Source source) : value{source < 0 } {}
53+ bool value;
5254};
53- template <typename Target, typename Source>
55+ template <typename Target, typename Source>
5456struct would_underflow <Target, Source, true , true > {
55- // When Source and Target are signed, the promotion rules apply sensibly so we do not
56- // need to do anything
57- would_underflow (Source source) : value{source < std::numeric_limits<Target>::min ()} {}
58- bool value;
57+ // When Source and Target are signed, the promotion rules apply sensibly so we do
58+ // not need to do anything
59+ would_underflow (Source source)
60+ : value{source < std::numeric_limits<Target>::min ()} {}
61+ bool value;
5962};
6063
61- template <typename Target,
62- typename Source,
63- bool target_is_signed = std::is_signed<Target>::value,
64- bool source_is_signed = std::is_signed<Source>::value,
65- typename = typename std::enable_if<
66- std::is_integral<Target>::value &&
67- std::is_integral<Source>::value
68- >::type>
64+ template <
65+ typename Target,
66+ typename Source,
67+ bool target_is_signed = std::is_signed<Target>::value,
68+ bool source_is_signed = std::is_signed<Source>::value,
69+ typename = typename std::enable_if<
70+ std::is_integral<Target>::value &&
71+ std::is_integral<Source>::value
72+ >::type
73+ >
6974struct would_overflow {
70- // The default case is Source and Target having the same signedness, the promotion
71- // rules also apply sensibly here so nothing special needs to be done
72- would_overflow (Source source) : value{source > std::numeric_limits<Target>::max ()} {}
73- bool value;
75+ // The default case is Source and Target having the same signedness, the promotion
76+ // rule also apply sensibly here so nothing special needs to be done
77+ would_overflow (Source source)
78+ : value{source > std::numeric_limits<Target>::max ()} {}
79+ bool value;
7480};
75- template <typename Target, typename Source>
76- struct would_overflow <Target, Source, false , true > {
77- // When Target is unsigned and Source is signed, we cannot rely on the promotion
78- // rules.
79- would_overflow (Source source)
80- : value{ sizeof (Target) >= sizeof (Source)
81- // Given Source is signed, Target being unsigned and having at least the
82- // same size makes impossible to overflow
83- ? false
84- // Source being larger than Target makes it safe to cast the maximum value
85- // of Target to Source
86- : source > static_cast <Source>(std::numeric_limits<Target>::max ())} {}
87- bool value;
81+ template <typename Target, typename Source>
82+ struct would_overflow <Target, Source, false , true > {
83+ // When Target is unsigned and Source is signed, we cannot rely on the promotion
84+ // rule.
85+ would_overflow (Source source)
86+ : value{
87+ sizeof (Target) >= sizeof (Source)
88+ // Given Source is signed, Target being unsigned and having at least the
89+ // same size makes impossible to overflow
90+ ? false
91+ // Source being larger than Target makes it safe to cast the maximum value
92+ // of Target to Source
93+ : source > static_cast <Source>(std::numeric_limits<Target>::max ())
94+ } {}
95+ bool value;
8896};
89- template <typename Target, typename Source>
97+ template <typename Target, typename Source>
9098struct would_overflow <Target, Source, true , false > {
91- // When Target is signed and Source is unsigned, we cannot rely on the promotion
92- // rules.
93- would_overflow (Source source)
94- : value{ sizeof (Target) > sizeof (Source)
95- // Target being larger than Source makes it impossible to overflow
96- ? false
97- // Source being unsigned and having at least the size of Target makes it
98- // safe to cast the maximum value of Target to Source
99- : source > static_cast <Source>(std::numeric_limits<Target>::max ())} {}
100- bool value;
99+ // When Target is signed and Source is unsigned, we cannot rely on the promotion
100+ // rule.
101+ would_overflow (Source source)
102+ : value{
103+ sizeof (Target) > sizeof (Source)
104+ // Target being larger than Source makes it impossible to overflow
105+ ? false
106+ // Source being unsigned and having at least the size of Target makes it
107+ // safe to cast the maximum value of Target to Source
108+ : source > static_cast <Source>(std::numeric_limits<Target>::max ())
109+ } {}
110+ bool value;
101111};
102112
103- template <typename Target,
104- typename Source,
105- typename = typename std::enable_if<
106- std::is_integral<Target>::value &&
107- std::is_integral<Source>::value
108- >::type>
113+ template <
114+ typename Target,
115+ typename Source,
116+ typename = typename std::enable_if<
117+ std::is_integral<Target>::value &&
118+ std::is_integral<Source>::value
119+ >::type
120+ >
109121Target integral_cast (Source source) {
110- if (would_underflow<Target, Source>(source).value ) {
111- throw std::underflow_error{" casting from Source to Target causes an underflow error" };
112- }
113- if (would_overflow<Target, Source>(source).value ) {
114- throw std::overflow_error{" casting from Source to Target causes an overflow error" };;
115- }
122+ if (would_underflow<Target, Source>(source).value ) {
123+ throw std::underflow_error{
124+ " casting from Source to Target causes an underflow error"
125+ };
126+ }
127+ if (would_overflow<Target, Source>(source).value ) {
128+ throw std::overflow_error{
129+ " casting from Source to Target causes an overflow error"
130+ };
131+ }
116132
117- return static_cast <Target>(source);
118- }
133+ return static_cast <Target>(source);
119134}
135+ } // namespace detail
120136
121137template <typename Clock, typename Duration>
122138struct as <std::chrono::time_point<Clock, Duration>> {
0 commit comments