OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2017 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <algorithm> | |
12 #include <limits> | |
13 | |
14 #include "webrtc/base/safe_minmax.h" | |
15 #include "webrtc/test/gtest.h" | |
16 | |
17 namespace rtc { | |
18 | |
19 namespace { | |
20 | |
21 // Functions that check that SafeMin() and SafeMax() return the specified type. | |
22 // The functions that end in "R" use an explicitly given return type. | |
23 | |
24 template <typename T1, typename T2, typename Tmin, typename Tmax> | |
25 constexpr bool TypeCheckMinMax() { | |
26 return std::is_same<decltype(SafeMin(std::declval<T1>(), std::declval<T2>())), | |
27 Tmin>::value && | |
28 std::is_same<decltype(SafeMax(std::declval<T1>(), std::declval<T2>())), | |
29 Tmax>::value; | |
30 } | |
31 | |
32 template <typename T1, typename T2, typename R> | |
33 constexpr bool TypeCheckMinR() { | |
34 return std::is_same< | |
35 decltype(SafeMin<R>(std::declval<T1>(), std::declval<T2>())), R>::value; | |
36 } | |
37 | |
38 template <typename T1, typename T2, typename R> | |
39 constexpr bool TypeCheckMaxR() { | |
40 return std::is_same< | |
41 decltype(SafeMax<R>(std::declval<T1>(), std::declval<T2>())), R>::value; | |
42 } | |
43 | |
44 // clang-format off | |
45 | |
46 // SafeMin/SafeMax: Check that all combinations of signed/unsigned 8/64 bits | |
47 // give the correct default result type. | |
48 static_assert(TypeCheckMinMax< int8_t, int8_t, int8_t, int8_t>(), ""); | |
49 static_assert(TypeCheckMinMax< int8_t, uint8_t, int8_t, uint8_t>(), ""); | |
50 static_assert(TypeCheckMinMax< int8_t, int64_t, int64_t, int64_t>(), ""); | |
51 static_assert(TypeCheckMinMax< int8_t, uint64_t, int8_t, uint64_t>(), ""); | |
52 static_assert(TypeCheckMinMax< uint8_t, int8_t, int8_t, uint8_t>(), ""); | |
53 static_assert(TypeCheckMinMax< uint8_t, uint8_t, uint8_t, uint8_t>(), ""); | |
54 static_assert(TypeCheckMinMax< uint8_t, int64_t, int64_t, int64_t>(), ""); | |
55 static_assert(TypeCheckMinMax< uint8_t, uint64_t, uint8_t, uint64_t>(), ""); | |
56 static_assert(TypeCheckMinMax< int64_t, int8_t, int64_t, int64_t>(), ""); | |
57 static_assert(TypeCheckMinMax< int64_t, uint8_t, int64_t, int64_t>(), ""); | |
58 static_assert(TypeCheckMinMax< int64_t, int64_t, int64_t, int64_t>(), ""); | |
59 static_assert(TypeCheckMinMax< int64_t, uint64_t, int64_t, uint64_t>(), ""); | |
60 static_assert(TypeCheckMinMax<uint64_t, int8_t, int8_t, uint64_t>(), ""); | |
61 static_assert(TypeCheckMinMax<uint64_t, uint8_t, uint8_t, uint64_t>(), ""); | |
62 static_assert(TypeCheckMinMax<uint64_t, int64_t, int64_t, uint64_t>(), ""); | |
63 static_assert(TypeCheckMinMax<uint64_t, uint64_t, uint64_t, uint64_t>(), ""); | |
64 | |
65 // SafeMin/SafeMax: Check that we can use enum types. | |
66 enum DefaultE { kFoo = -17 }; | |
67 enum UInt8E : uint8_t { kBar = 17 }; | |
68 static_assert(TypeCheckMinMax<unsigned, DefaultE, int, unsigned>(), ""); | |
69 static_assert(TypeCheckMinMax<unsigned, UInt8E, uint8_t, unsigned>(), ""); | |
70 static_assert(TypeCheckMinMax<DefaultE, UInt8E, int, int>(), ""); | |
71 | |
72 using ld = long double; | |
73 | |
74 // SafeMin/SafeMax: Check that all floating-point combinations give the | |
75 // correct result type. | |
76 static_assert(TypeCheckMinMax< float, float, float, float>(), ""); | |
77 static_assert(TypeCheckMinMax< float, double, double, double>(), ""); | |
78 static_assert(TypeCheckMinMax< float, ld, ld, ld>(), ""); | |
79 static_assert(TypeCheckMinMax<double, float, double, double>(), ""); | |
80 static_assert(TypeCheckMinMax<double, double, double, double>(), ""); | |
81 static_assert(TypeCheckMinMax<double, ld, ld, ld>(), ""); | |
82 static_assert(TypeCheckMinMax< ld, float, ld, ld>(), ""); | |
83 static_assert(TypeCheckMinMax< ld, double, ld, ld>(), ""); | |
84 static_assert(TypeCheckMinMax< ld, ld, ld, ld>(), ""); | |
85 | |
86 // clang-format on | |
87 | |
88 // SafeMin/SafeMax: Check some cases of explicitly specified return type. The | |
89 // commented-out lines give compilation errors due to the requested return type | |
90 // being too small or requiring an int<->float conversion. | |
91 static_assert(TypeCheckMinR<int8_t, int8_t, int16_t>(), ""); | |
92 // static_assert(TypeCheckMinR<int8_t, int8_t, float>(), ""); | |
93 static_assert(TypeCheckMinR<uint32_t, uint64_t, uint32_t>(), ""); | |
94 // static_assert(TypeCheckMaxR<uint64_t, float, float>(), ""); | |
ossu
2017/04/24 13:22:27
I uncommented this line and the code still compile
kwiberg-webrtc
2017/04/25 09:26:54
Thanks for checking! That error was supposed to be
| |
95 // static_assert(TypeCheckMaxR<uint64_t, double, float>(), ""); | |
96 static_assert(TypeCheckMaxR<uint32_t, int32_t, uint32_t>(), ""); | |
97 // static_assert(TypeCheckMaxR<uint32_t, int32_t, int32_t>(), ""); | |
98 | |
99 template <typename T1, typename T2, typename Tmin, typename Tmax> | |
100 constexpr bool CheckMinMax(T1 a, T2 b, Tmin min, Tmax max) { | |
101 return TypeCheckMinMax<T1, T2, Tmin, Tmax>() && SafeMin(a, b) == min && | |
102 SafeMax(a, b) == max; | |
103 } | |
104 | |
105 // SafeMin/SafeMax: Check a few values. | |
106 static_assert(CheckMinMax(int8_t{1}, int8_t{-1}, int8_t{-1}, int8_t{1}), ""); | |
107 static_assert(CheckMinMax(uint8_t{1}, int8_t{-1}, int8_t{-1}, uint8_t{1}), ""); | |
108 static_assert(CheckMinMax(uint8_t{5}, uint64_t{2}, uint8_t{2}, uint64_t{5}), | |
109 ""); | |
110 static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), | |
111 std::numeric_limits<uint32_t>::max(), | |
112 std::numeric_limits<int32_t>::min(), | |
113 std::numeric_limits<uint32_t>::max()), | |
114 ""); | |
115 static_assert(CheckMinMax(std::numeric_limits<int32_t>::min(), | |
116 std::numeric_limits<uint16_t>::max(), | |
117 std::numeric_limits<int32_t>::min(), | |
118 int32_t{std::numeric_limits<uint16_t>::max()}), | |
119 ""); | |
120 // static_assert(CheckMinMax(1.f, 2, 1.f, 2.f), ""); | |
121 static_assert(CheckMinMax(1.f, 0.0, 0.0, 1.0), ""); | |
122 | |
123 } // namespace | |
124 | |
125 // clang-format off | |
126 | |
127 // These functions aren't used in the tests, but it's useful to look at the | |
128 // compiler output for them, and verify that (1) the same-signedness *Safe | |
129 // functions result in exactly the same code as their *Ref counterparts, and | |
130 // that (2) the mixed-signedness *Safe functions have just a few extra | |
131 // arithmetic and logic instructions (but no extra control flow instructions). | |
132 int32_t TestMinRef( int32_t a, int32_t b) { return std::min(a, b); } | |
133 uint32_t TestMinRef( uint32_t a, uint32_t b) { return std::min(a, b); } | |
134 int32_t TestMinSafe( int32_t a, int32_t b) { return SafeMin(a, b); } | |
135 int32_t TestMinSafe( int32_t a, uint32_t b) { return SafeMin(a, b); } | |
136 int32_t TestMinSafe(uint32_t a, int32_t b) { return SafeMin(a, b); } | |
137 uint32_t TestMinSafe(uint32_t a, uint32_t b) { return SafeMin(a, b); } | |
138 | |
139 // clang-format on | |
140 | |
141 } // namespace rtc | |
OLD | NEW |