1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include "cast.h"
#include <library/cpp/testing/unittest/registar.h>
class TGenericCastsTest: public TTestBase {
UNIT_TEST_SUITE(TGenericCastsTest);
UNIT_TEST(TestVerifyDynamicCast)
UNIT_TEST(TestIntegralCast)
UNIT_TEST(TestEnumCast)
UNIT_TEST(TestToUnderlying)
UNIT_TEST(TestBitCast)
UNIT_TEST_SUITE_END();
private:
struct TAaa {
virtual ~TAaa() = default;
};
struct TBbb: public TAaa {};
inline void TestVerifyDynamicCast() {
TBbb bbb;
TAaa* aaa = &bbb;
TAaa* aaa2 = VerifyDynamicCast<TBbb*>(aaa);
UNIT_ASSERT(aaa == aaa2);
}
void TestIntegralCast() {
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<ui32>(-5), TBadCastException);
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<ui16>(static_cast<i32>(Max<ui16>() + 10)), TBadCastException);
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<ui16>(static_cast<ui32>(Max<ui16>() + 10)), TBadCastException);
}
inline void TestEnumCast() {
enum A {
AM1 = -1
};
enum B: int {
BM1 = -1
};
enum class C: unsigned short {
CM1 = 1
};
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<unsigned int>(AM1), TBadCastException);
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<unsigned int>(BM1), TBadCastException);
UNIT_ASSERT_EXCEPTION(SafeIntegerCast<C>(AM1), TBadCastException);
UNIT_ASSERT_EXCEPTION(static_cast<int>(SafeIntegerCast<C>(BM1)), TBadCastException);
UNIT_ASSERT(SafeIntegerCast<A>(BM1) == AM1);
UNIT_ASSERT(SafeIntegerCast<B>(AM1) == BM1);
UNIT_ASSERT(SafeIntegerCast<A>(C::CM1) == 1);
UNIT_ASSERT(SafeIntegerCast<B>(C::CM1) == 1);
UNIT_ASSERT(SafeIntegerCast<A>(-1) == AM1);
UNIT_ASSERT(SafeIntegerCast<B>(-1) == BM1);
UNIT_ASSERT(SafeIntegerCast<C>(1) == C::CM1);
}
void TestToUnderlying() {
enum A {
AM1 = -1
};
enum B: int {
BM1 = -1
};
enum class C: unsigned short {
CM1 = 1
};
static_assert(static_cast<std::underlying_type_t<A>>(AM1) == ToUnderlying(AM1), "");
static_assert(static_cast<std::underlying_type_t<B>>(BM1) == ToUnderlying(BM1), "");
static_assert(static_cast<std::underlying_type_t<C>>(C::CM1) == ToUnderlying(C::CM1), "");
static_assert(std::is_same<std::underlying_type_t<A>, decltype(ToUnderlying(AM1))>::value, "");
static_assert(std::is_same<std::underlying_type_t<B>, decltype(ToUnderlying(BM1))>::value, "");
static_assert(std::is_same<std::underlying_type_t<C>, decltype(ToUnderlying(C::CM1))>::value, "");
UNIT_ASSERT_VALUES_EQUAL(static_cast<std::underlying_type_t<A>>(AM1), ToUnderlying(AM1));
UNIT_ASSERT_VALUES_EQUAL(static_cast<std::underlying_type_t<B>>(BM1), ToUnderlying(BM1));
UNIT_ASSERT_VALUES_EQUAL(static_cast<std::underlying_type_t<C>>(C::CM1), ToUnderlying(C::CM1));
}
void TestBitCast() {
// Change sign of float
{
const float floatValue = 17.33f;
ui32 ui32Value = BitCast<ui32>(floatValue);
ui32Value ^= (ui32)1 << 31;
UNIT_ASSERT_VALUES_EQUAL(-floatValue, BitCast<float>(ui32Value));
}
// Unpack ui64 into a struct
{
const ui64 value = 0x1122334455667788;
struct TStruct {
ui32 a;
ui16 b;
ui8 c;
ui8 d;
};
auto structValue = BitCast<TStruct>(value);
UNIT_ASSERT_VALUES_EQUAL(structValue.a, 0x55667788);
UNIT_ASSERT_VALUES_EQUAL(structValue.b, 0x3344);
UNIT_ASSERT_VALUES_EQUAL(structValue.c, 0x22);
UNIT_ASSERT_VALUES_EQUAL(structValue.d, 0x11);
}
}
};
UNIT_TEST_SUITE_REGISTRATION(TGenericCastsTest);
|