-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction_test2.cpp
131 lines (111 loc) · 2.83 KB
/
function_test2.cpp
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
// 関数または関数的なものを保持して後から呼び出すような機能をどのように実装するかを確認するためのテスト。
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gtest/gtest.h>
#include <functional>
// Actionクラスを直接使うのが面倒なので…
class ActionBase
{
public:
virtual ~ActionBase() {}
virtual int invoke(int a, int b) = 0;
};
// 関数または関数的なものを保持したり後から呼び出したりするためのクラス。
template <typename F>
class Action : public ActionBase
{
public:
Action(F action);
virtual int invoke(int a, int b);
private:
F action_;
};
// コンストラクタ。保持している。
template <typename F>
Action<F>::Action(F action)
: action_(action)
{
}
// 保持したものを呼び出す。
template <typename F>
int Action<F>::invoke(int a, int b)
{
return action_(a, b);
}
// Actionオブジェクトを生成する。Actionクラスを直接記述するのが面倒なのでこの関数に任せている。
template <typename F>
ActionBase *new_action(F action)
{
return new Action<F>(action);
}
// ローカル関数の例。
static int add(int a, int b)
{
return a + b;
}
// 関数オブジェクトの例。
struct FuncObj
{
int operator()(int a, int b) const
{
return a + b;
}
};
// staticなメンバー関数の例。
struct StaticMemFunc
{
static int add_static(int a, int b)
{
return a + b;
}
};
// staticではないメンバー関数の例。
struct MemFunc
{
int add(int a, int b)
{
return a + b;
}
};
// ローカル関数を使った実装例。
TEST(FunctionTest2, LocalFunc)
{
ActionBase *a = new_action(&add);
EXPECT_EQ(5, a->invoke(2, 3));
}
// 関数オブジェクトを使った実装例。
TEST(FunctionTest2, FuncObj)
{
FuncObj ta;
ActionBase *a = new_action(ta);
EXPECT_EQ(5, a->invoke(2, 3));
}
// staticなメンバー関数を使った実装例。
TEST(FunctionTest2, StaticMemFunc)
{
ActionBase *a = new_action(std::bind(StaticMemFunc::add_static, std::placeholders::_1, std::placeholders::_2));
EXPECT_EQ(5, a->invoke(2, 3));
}
// staticではないメンバー関数を使った実装例。
TEST(FunctionTest2, MemFunc)
{
MemFunc ta;
ActionBase *a = new_action(std::bind(&MemFunc::add, &ta, std::placeholders::_1, std::placeholders::_2));
EXPECT_EQ(5, a->invoke(2, 3));
}
// lambdaでの実装例。
TEST(FunctionTest2, BoostLambda)
{
auto a = new_action([](int x, int y){ return x + y; });
EXPECT_EQ(5, a->invoke(2, 3));
}
#if defined(__APPLE__) && defined(__BLOCKS__)
// ブロックでの実装例。
TEST(FunctionTest2, BlockObject)
{
ActionBase *a = new_action(^(int a, int b) {return a + b;});
EXPECT_EQ(5, a->invoke(2, 3));
}
#endif // defined(__APPLE__) && defined(__BLOCKS__)
// TODO: C++0xのラムダ関数での例を追加する。