Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: base/numerics/safe_conversions.h

Issue 2481903002: Make checked_cast a constexpr (Closed)
Patch Set: nit Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/numerics/safe_numerics_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ 5 #ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_
6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_ 6 #define BASE_NUMERICS_SAFE_CONVERSIONS_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <limits> 10 #include <limits>
(...skipping 23 matching lines...) Expand all
34 } 34 }
35 35
36 template <typename T> 36 template <typename T>
37 constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, 37 constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed,
38 bool>::type IsValueNegative(T) { 38 bool>::type IsValueNegative(T) {
39 static_assert(std::numeric_limits<T>::is_specialized, 39 static_assert(std::numeric_limits<T>::is_specialized,
40 "Argument must be numeric."); 40 "Argument must be numeric.");
41 return false; 41 return false;
42 } 42 }
43 43
44 // checked_cast<> is analogous to static_cast<> for numeric types, 44 // Just fires a CHECK(false). Used for numeric boundary errors.
45 // except that it CHECKs that the specified numeric conversion will not 45 struct CheckOnFailure {
46 // overflow or underflow. NaN source will always trigger a CHECK.
47 template <typename Dst, typename Src>
48 inline Dst checked_cast(Src value) {
49 CHECK(IsValueInRangeForNumericType<Dst>(value));
50 return static_cast<Dst>(value);
51 }
52
53 // HandleNaN will cause this class to CHECK(false).
54 struct SaturatedCastNaNBehaviorCheck {
55 template <typename T> 46 template <typename T>
56 static T HandleNaN() { 47 static T HandleFailure() {
57 CHECK(false); 48 CHECK(false);
58 return T(); 49 return T();
59 } 50 }
60 }; 51 };
61 52
53 // checked_cast<> is analogous to static_cast<> for numeric types,
54 // except that it CHECKs that the specified numeric conversion will not
55 // overflow or underflow. NaN source will always trigger a CHECK.
56 template <typename Dst,
57 class CheckHandler = CheckOnFailure,
58 typename Src>
59 constexpr Dst checked_cast(Src value) {
60 // This throws a compile-time error on evaluating the constexpr if it can be
61 // determined at compile-time as failing, otherwise it will CHECK at runtime.
62 return IsValueInRangeForNumericType<Dst>(value)
63 ? static_cast<Dst>(value)
64 : CheckHandler::template HandleFailure<Dst>();
65 }
66
62 // HandleNaN will return 0 in this case. 67 // HandleNaN will return 0 in this case.
63 struct SaturatedCastNaNBehaviorReturnZero { 68 struct SaturatedCastNaNBehaviorReturnZero {
64 template <typename T> 69 template <typename T>
65 static constexpr T HandleNaN() { 70 static constexpr T HandleFailure() {
66 return T(); 71 return T();
67 } 72 }
68 }; 73 };
69 74
70 namespace internal { 75 namespace internal {
71 // This wrapper is used for C++11 constexpr support by avoiding the declaration 76 // This wrapper is used for C++11 constexpr support by avoiding the declaration
72 // of local variables in the saturated_cast template function. 77 // of local variables in the saturated_cast template function.
73 template <typename Dst, class NaNHandler, typename Src> 78 template <typename Dst, class NaNHandler, typename Src>
74 constexpr Dst saturated_cast_impl(const Src value, 79 constexpr Dst saturated_cast_impl(const Src value,
75 const RangeConstraint constraint) { 80 const RangeConstraint constraint) {
76 return constraint == RANGE_VALID 81 return constraint == RANGE_VALID
77 ? static_cast<Dst>(value) 82 ? static_cast<Dst>(value)
78 : (constraint == RANGE_UNDERFLOW 83 : (constraint == RANGE_UNDERFLOW
79 ? std::numeric_limits<Dst>::min() 84 ? std::numeric_limits<Dst>::min()
80 : (constraint == RANGE_OVERFLOW 85 : (constraint == RANGE_OVERFLOW
81 ? std::numeric_limits<Dst>::max() 86 ? std::numeric_limits<Dst>::max()
82 : (constraint == RANGE_INVALID 87 : (constraint == RANGE_INVALID
83 ? NaNHandler::template HandleNaN<Dst>() 88 ? NaNHandler::template HandleFailure<Dst>()
84 : (NOTREACHED(), static_cast<Dst>(value))))); 89 : (NOTREACHED(), static_cast<Dst>(value)))));
85 } 90 }
86 } // namespace internal 91 } // namespace internal
87 92
88 // saturated_cast<> is analogous to static_cast<> for numeric types, except 93 // saturated_cast<> is analogous to static_cast<> for numeric types, except
89 // that the specified numeric conversion will saturate rather than overflow or 94 // that the specified numeric conversion will saturate rather than overflow or
90 // underflow. NaN assignment to an integral will defer the behavior to a 95 // underflow. NaN assignment to an integral will defer the behavior to a
91 // specified class. By default, it will return 0. 96 // specified class. By default, it will return 0.
92 template <typename Dst, 97 template <typename Dst,
93 class NaNHandler = SaturatedCastNaNBehaviorReturnZero, 98 class NaNHandler = SaturatedCastNaNBehaviorReturnZero,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 private: 162 private:
158 const T value_; 163 const T value_;
159 }; 164 };
160 165
161 // Explicitly make a shorter size_t typedef for convenience. 166 // Explicitly make a shorter size_t typedef for convenience.
162 typedef StrictNumeric<size_t> SizeT; 167 typedef StrictNumeric<size_t> SizeT;
163 168
164 } // namespace base 169 } // namespace base
165 170
166 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_ 171 #endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_
OLDNEW
« no previous file with comments | « no previous file | base/numerics/safe_numerics_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698