模版默认参数小探
我们知道,复杂模版一般都有多个参数且大多数参数都有默认值。假设我们的模版类型有9个参数,其中后7个参数都指定了默认值,且大多数情况下我们都不需要手动填写这些默认参数。这个时候如果我们要给第九个参数指定一个非默认值,结果是我们不得不给前面的6个默认参数都填入模版实参,哪怕是默认值。
最近看到c++ template 中有这样的解决方案,能够实现只需我们填写那个我们需要填写的默认参数而不去关心其他的参数。下面是该方案的伪代码。
该方案测试代码:
最近看到c++ template 中有这样的解决方案,能够实现只需我们填写那个我们需要填写的默认参数而不去关心其他的参数。下面是该方案的伪代码。
1
2
//参数相关类型
3
4
5
class para1
6
{
7
public:
8
static void f() {}
9
};
10
class para2
11
{
12
public:
13
static void f() {}
14
};
15
16
class para
17
{
18
public:
19
typedef para1 p1;
20
typedef para2 p2;
21
};
22
23
class default_para_is : virtual public para
24
{
25
};
26
27
28
template <typename _para1>
29
class para1_is : virtual public para
30
{
31
public:
32
typedef _para1 p1;
33
};
34
35
template <typename _para2>
36
class para2_is : virtual public para
37
{
38
public:
39
typedef _para2 p2;
40
};
41
42
43
44
45
//参数区分装置
46
47
template <typename _para, int d>
48
class discriminator : public _para {};
49
50
template
51
<
52
typename _para1,
53
typename _para2
54
>
55
class para_selector :
56
public discriminator<_para1, 1>,
57
public discriminator<_para2, 2>
58
{
59
60
};
61
62
63
64
//参数使用者
65
66
template
67
<
68
typename _para1= default_para_is,
69
typename _para2= default_para_is
70
>
71
class user
72
{
73
public:
74
75
//这是我们要使用的类型选择器。
76
typedef para_selector<_para1, _para2> selector;
77
public:
78
void f()
79
{
80
selector::p1::f();
81
selector::p2::f();
82
}
83
};
84
85
86
//填充参数类型
87
88
89
class parameter1
90
{
91
public:
92
static void f()
93
{
94
cout << "p1.f()" << endl;
95
}
96
};
97
98
99
class parameter2
100
{
101
public:
102
static void f()
103
{
104
cout << "p2.f()" << endl;
105
}
106
};
107
108
109
//----------------------------------------------------------------------

2
//参数相关类型3

4

5
class para16
{7
public:8
static void f() {}9
};10
class para211
{12
public:13
static void f() {}14
};15

16
class para17
{18
public:19
typedef para1 p1;20
typedef para2 p2;21
};22

23
class default_para_is : virtual public para24
{25
};26

27

28
template <typename _para1>29
class para1_is : virtual public para30
{31
public:32
typedef _para1 p1;33
};34

35
template <typename _para2>36
class para2_is : virtual public para37
{38
public:39
typedef _para2 p2;40
};41

42

43

44

45
//参数区分装置46

47
template <typename _para, int d>48
class discriminator : public _para {};49

50
template 51
<52
typename _para1,53
typename _para254
>55
class para_selector :56
public discriminator<_para1, 1>,57
public discriminator<_para2, 2>58
{59

60
};61

62

63

64
//参数使用者65

66
template 67
<68
typename _para1= default_para_is,69
typename _para2= default_para_is70
>71
class user72
{73
public:74

75
//这是我们要使用的类型选择器。76
typedef para_selector<_para1, _para2> selector;77
public:78
void f()79
{80
selector::p1::f();81
selector::p2::f();82
}83
};84

85

86
//填充参数类型87

88

89
class parameter190
{91
public:92
static void f()93
{94
cout << "p1.f()" << endl;95
}96
};97

98

99
class parameter2100
{101
public:102
static void f()103
{104
cout << "p2.f()" << endl;105
}106
};107

108

109
//----------------------------------------------------------------------该方案测试代码:
1
//----------------------------------------------------------------------
2
3
4
5
6
//使用默认参数类型
7
8
user<> u1;
9
u1.f();
10
11
12
//指定参数类型:
13
// 1。能够指定任意一个参数的类型。
14
// 2。指定的参数满足交换律。
15
16
user<para2_is<parameter2> > u2;
17
u2.f();
18
19
user<para1_is<parameter1>, para2_is<parameter2> > u3;
20
u3.f();
21
22
23
user<para2_is<parameter2>, para1_is<parameter1> > u4;
24
u4.f();
25
26
27
//----------------------------------------------------------------------
//----------------------------------------------------------------------2

3

4

5

6
//使用默认参数类型7

8
user<> u1;9
u1.f();10

11

12
//指定参数类型:13
// 1。能够指定任意一个参数的类型。14
// 2。指定的参数满足交换律。15

16
user<para2_is<parameter2> > u2;17
u2.f();18

19
user<para1_is<parameter1>, para2_is<parameter2> > u3;20
u3.f();21

22

23
user<para2_is<parameter2>, para1_is<parameter1> > u4;24
u4.f();25

26

27
//----------------------------------------------------------------------
上述代码中,类型 user 使用了 para1 para2 两个类型,且两个类型都指定了默认模版实参。我们在给模版形参para2 指定非默认值得时候只是简单的调用设置参数函数user<para2_is<parameter2> > 就行了,并没有对 para1 进行实参填充,这正是我们想要的结果!。
对上述代码的几点说明:
1。上述代码有几个继承体系,但都是在编译期间进行的匹配,不会引起运行速度慢等问题。
2。该方案使用了模版的 trait 和 policy 技术。trait 实现了类型封装。policy 提供了隐式接口和编译期多态的支持。
3。如果模版参数并不是很多的情况下如此操作只会增加复杂度和出错的可能性。个人感觉参数个数比较多的情况下使用带来的好处是非常大的。


浙公网安备 33010602011771号