-
Notifications
You must be signed in to change notification settings - Fork 1
/
cppFriends.hpp
143 lines (121 loc) · 4.4 KB
/
cppFriends.hpp
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#ifndef CPPFRIENDS_CPPFRIENDS_HPP
#define CPPFRIENDS_CPPFRIENDS_HPP
#include <cstdint>
#include <iostream>
#include <list>
#include <string>
#include <type_traits>
#include <variant>
#include <boost/type_traits/function_traits.hpp>
// int32を32回以上シフトする実験
#define CPPFRIENDS_SHIFT_COUNT (35)
// result = RCXレジスタを破壊することを兼ねて敢えてこのような引数にしている
extern void Shift35ForInt32Asm(int32_t& result, int32_t src);
// int32を32回以上シフトする実験
// シフト回数を固定する
extern int32_t Shift35ForInt32(int32_t src);
// シフト回数を実行時に与える
extern int32_t ShiftForInt32(int32_t src, int32_t count);
// 定義した.cppとは別の.cppから参照される
// ヘッダで定義すると定数伝搬できるが、定数を変えた時に、
// インクルードしている.cppをすべてビルドしなければならない
extern const int g_externIntValue;
namespace {
// ある.cppでは使うが、他の.cppでは使わないインライン関数
inline int MyPopCount(short src) {
using T = boost::function_traits<decltype(__builtin_popcount)>::arg1_type;
static_assert(std::is_convertible<decltype(src), T>::value, "cannot convert");
return __builtin_popcount(src);
}
// __attribute__((always_inline))
int MySlowPopCount(unsigned int src) {
return (src) ? ((src & 1) + MySlowPopCount(src >> 1)) : 0;
}
}
// enum classは前方宣言できるので、メンバを増やしてもリコンパイルが必要とは限らない
enum class FriendType : int;
struct FriendTypeBox {
FriendType type_; // underlying typeがあればメンバは知らなくてよい
// 他に必要なメンバを追加する
};
class DynamicObjectMemFunc {
public:
DynamicObjectMemFunc(void) = default;
virtual ~DynamicObjectMemFunc() = default;
virtual void Clear(void) = 0;
virtual void Print(std::ostream& os) = 0;
// テスト用に敢えて公開している
uint64_t memberA_ {0};
uint64_t memberB_ {0};
};
class SubDynamicObjectMemFunc : public DynamicObjectMemFunc {
public:
SubDynamicObjectMemFunc(void) = default;
SubDynamicObjectMemFunc(uint64_t a, uint64_t b) : memberA_(a), memberB_(b) {}
virtual ~SubDynamicObjectMemFunc() = default;
virtual void Clear(void) override;
virtual void Print(std::ostream& os) override;
// テスト用に敢えて公開している
uint64_t memberA_ {0};
uint64_t memberB_ {0};
};
// .cppで定義した場合、どこかでインスタンス化しないと、vtableが作られないかもしれない
class ExtraMemFunc : public SubDynamicObjectMemFunc {
public:
virtual ~ExtraMemFunc() = default;
virtual void Print(std::ostream& os) override;
};
class MyStringList {
public:
MyStringList(size_t n);
virtual ~MyStringList() = default;
virtual void Print(std::ostream& os) const;
virtual void Pop(void);
virtual void Clear(void);
// 本来メンバ変数を見せるものではないが、悪い見本として
std::list<std::string> dataSet_;
};
// 本当にconstデータなら書き換えられない
constexpr size_t ConstantArraySampleSize = 0x10000;
extern const uint8_t ConstantArraySample[ConstantArraySampleSize];
extern const int& ConstantIntRefSample;
// 呼び出し側には定義を見せない
struct IntHolderImplicit {
IntHolderImplicit(int arg);
operator int&();
operator int() const;
int value_ {0};
};
struct IntHolderExplicit {
explicit IntHolderExplicit(int arg);
int Get() const;
int value_ {0};
};
class VarBase {
public:
virtual ~VarBase() = default;
virtual void Print(std::ostream& os) const = 0;
};
class VarDerived1 : public VarBase {
public:
virtual ~VarDerived1() = default;
virtual void Print(std::ostream& os) const;
};
class VarDerived2 : public VarBase {
public:
virtual ~VarDerived2() = default;
virtual void Print(std::ostream& os) const;
};
using VarSample = std::variant<std::monostate, const VarDerived1, const VarDerived2>;
extern VarSample GetVoid();
extern VarSample GetDerived1();
extern VarSample GetDerived2();
#endif // CPPFRIENDS_CPPFRIENDS_HPP
/*
Local Variables:
mode: c++
coding: utf-8-dos
tab-width: nil
c-file-style: "stroustrup"
End:
*/