??xml version="1.0" encoding="utf-8" standalone="yes"?> 用法举例 q是使用Xpressive动态语义定义的例子Q其中sregex::compile函数~译一个表C正则文法的Ԍq返回一个正则对象sregex 如果惛_一个串中查扄合该文法的子Ԍ可以使用regex_searchQ用法和regex_match一P此外q可以用regex_replace来进行替换?br> q将定义一个表C金额的Ԍ其中_d表示一个数字,相当于串 $\d+.\d\d q样s表示为用括号括v来的re expression定义了一个四则表辑ּQ注意其中group的定义?br>q里必须使用by_ref是因为Xpressive默认是值拷贝,如果q里使用默认的方式,那么会造成一个无限@环?br> 很多时候写一个类的时候,需要多个模版参敎ͼ例如一个遗传算法的法c,需要一个模版参数来指定交配方式Q另一个模版参数来指定子代选择的方式,q要一个参数来指定变异的方式。那么一般来_q个cM写成Q?/p>
template<class T //描述问题的一个类 q样用户要用该cȝ时候,可以直接指定TQ就行了Q然而如果要指定变异方式Q那么就必须把所有的参数都显式的写出来,很不方便 546提供了一U有效的ҎQ可以让我们仅仅指定变异参数Q而不用写出另两个Policy 预备知识: 如何在一个TypeList中查找一个类型的子类Q?br>首先要有一个IsDerivedFrom<Base, T> 然后FindChild容易了 template <> typedef typename Select<IsDerivedFrom<Base, typename List::Type> >::Type Type; 当然q要对一些特D情况进行特化,例如NullType 实际操作Q?br>首先需要给3个Policy3个基c,分别?br>class AvgCrossPolicyBase{}; 定义一个宏 下面要写一些选择?用于把合适的cd选择出来Q如果没扑ֈQ则要用默认的cd 好啦Q现在整个类的声明可以写?/p>
template<class T
发信? shifan (学习云技?, 杉K: C++
?nbsp; ? 伪typeof
发信? 飘ؓ水云?(Tue Dec 19 16:38:45 2006), 转信
2 用标准C++实现typeof是不可能?br> 3 q个是我写的一个approached typeof
4 所有需要被静态反出来的cd必须先用DECL_TYPE注册
5 模板如果仅仅带有1个参数可以用DECL_TEMPLATE_1注册
6 多个参数的模板还不支持。?br> 7 主要是没惛_~码
8
9 d能注?4个类?br>10 可以通过MAX_TYPE_NUMBER讄
11
12 支持的模板嵌套层数大Uؓ32 Q?nbsp;log2(MAX_TYPE_NUMBER)
13 MAX_TYPE_NUMBER必须?的整ơ数q?br>14 */
15 namespace my_typeof
16 {
17
18 const int MAX_TYPE_NUMBER = 64;
19
20 template <int N>
21 struct dummy
22 {
23 int a[N];
24 };
25
26
27 template <int N, typename Arg1>
28 struct select_by_number_1;
29
30 template <int N>
31 struct select_by_number
32 {
33 typedef typename select_by_number_1<N % MAX_TYPE_NUMBER, typename
34 select_by_number<N / MAX_TYPE_NUMBER>::type>::type type;
35 };
36
37
38 template <typename T>
39 struct number_of
40 {
41 static const int v = sizeof(generic_f(*(T*)0)) / sizeof(int);
42 };
43
44
45 #define DECL_TYPE(T, N) \
46 namespace my_typeof{ \
47 template<>\
48 struct select_by_number<N> \
49 {\
50 typedef T type;\
51 };\
52 dummy <N> generic_f(const T&);}
53
54
55 #define DECL_TEMPLATE_1(T, N) \
56 namespace my_typeof{ \
57 template<typename Arg1>\
58 struct select_by_number_1<N, Arg1>\
59 {\
60 typedef T<Arg1> type;\
61 };\
62 template <typename Arg1>\
63 dummy<N + number_of<Arg1>::v * MAX_TYPE_NUMBER > generic_f(const T<Arg1>&);}
64
65
66
67 #define TYPE_OF(x) my_typeof::select_by_number<sizeof(my_typeof::generic_f(x)) /
68 sizeof (int)>::type
69
70 }
71
72
73 //sample
74 #include <iostream>
75 #include <vector>
76 #include <list>
77
78
79 DECL_TYPE(int, 1);
80 DECL_TEMPLATE_1(std::vector, 2);
81 DECL_TEMPLATE_1(std::list, 3);
82 DECL_TYPE(double, 4)
83
84 using namespace std;
85 int main(int, char*[])
86 {
87 vector<list<vector<list<double> > > > v1;
88 TYPE_OF(v1) v2;
89 v1 = v2;
90 return 0;
91 }
92
93
--
You well 撒法QYou well all 撒法Q?br>
?内容修改:·shifan ?Dec 21 14:21:57 修改本文内容·[FROM: shifan]
?来源:·飘ؓ水云?freecity.cn·[FROM: shifan]
]]>
要多个位必须写很多遍high_bit_mask_t
使用low_bits_mask_t也不能完全解决问?br>所以自qTypelist的U写法写了一?/p>
bit_mask<INT_LIST_2(2, 3)>::valueq回一个|该值的W??位被|ؓ1
其余位ؓ0
2 namespace multi_bit_mask
3 {
4 namespace details
5 {
6
7 template <typename T>
8 struct get_size
9 {
10 enum {size = sizeof(T)};
11 };
12
13 template <int Bit>
14 struct bit_storage
15 {
16 typedef typename bit_storage<Bit - 1>::storage_type storage_type;
17 };
18
19 //---------platform dependency-----------------------
20
21 typedef unsigned int smallest_storage_type;
22 typedef unsigned long long largest_storage_type;
23
24
25
26 template <>
27 struct bit_storage<0>
28 {
29 typedef smallest_storage_type storage_type;
30 };
31
32 template <>
33 struct bit_storage<get_size<smallest_storage_type>::size * 8>
34 {
35 typedef largest_storage_type storage_type;
36 };
37
38 //disable the 65th bit
39 template <>
40 struct bit_storage<get_size<largest_storage_type>::size * 8>
41 {
42 typedef void storage_type;
43 };
44
45 //---------end of platform dependency----------------
46
47
48 template <unsigned int N, typename Next>
49 struct int_list
50 {
51 typedef typename bit_storage<N>::storage_type storage_type;
52 static const storage_type value = N;
53 typedef Next next;
54 };
55
56 struct null_type{};
57
58 template<typename T1, typename T2, bool is_first>
59 struct selector
60 {
61 typedef T1 type;
62 };
63
64 template<typename T1, typename T2>
65 struct compare_type
66 {
67 const static bool is_larger = sizeof(T1) > sizeof(T2);
68 typedef typename selector<T1, T2, is_larger>::type large_type;
69 typedef typename selector<T1, T2, !is_larger>::type small_type;
70 };
71
72
73
74 template<typename T1, typename T2>
75 struct selector<T1, T2, false>
76 {
77 typedef T2 type;
78 };
79
80 template <typename List>
81 class find_largest_storage
82 {
83 typedef typename find_largest_storage<typename List::next>::storage_type T1;
84 typedef typename bit_storage<List::value>::storage_type T2;
85 public:
86 typedef typename compare_type<T1, T2>::large_type storage_type;
87 };
88
89 template <>
90 class find_largest_storage<null_type>
91 {
92 public:
93 typedef smallest_storage_type storage_type;
94 };
95
96
97 }
98
99
100
101
102
103 template <int N>
104 struct single_bit_mask
105 {
106 typedef typename details::bit_storage<N>::storage_type storage_type;
107 static const storage_type value
108 = static_cast<storage_type>(single_bit_mask<N - 1>::value) * 2;
109 };
110
111 template <>
112 struct single_bit_mask<0>
113 {
114 typedef details::bit_storage<0>::storage_type storage_type;
115 static const storage_type value = 1;
116 };
117
118
119 typedef details::null_type null_type;
120
121 template <int N, typename Next>
122 struct int_list_t : public details::int_list<N, Next> {};
123
124 template <typename List>
125 struct bit_mask
126 {
127 public:
128
129 typedef typename details::find_largest_storage<List>::storage_type storage_type;
130
131 static const storage_type value
132 = static_cast<storage_type>(single_bit_mask<List::value>::value)
133 | static_cast<storage_type>(bit_mask<typename List::next>::value);
134 };
135
136 template <>
137 struct bit_mask<null_type>
138 {
139 typedef details::bit_storage<0>::storage_type storage_type;
140 static const storage_type value = 0;
141 };
142
143
144
145
146
147 #define INT_LIST_1(n1) multi_bit_mask::int_list_t<n1, multi_bit_mask::null_type>
148 #define INT_LIST_2(n1, n2) multi_bit_mask::int_list_t<n1, INT_LIST_1(n2) >
149 #define INT_LIST_3(n1, n2, n3) multi_bit_mask::int_list_t<n1, INT_LIST_2(n2, n3) >
150 #define INT_LIST_4(n1, n2, n3, n4) multi_bit_mask::int_list_t<n1, INT_LIST_3(n2, n3, n4) >
151 #define INT_LIST_5(n1, n2, n3, n4, n5) multi_bit_mask::int_list_t<n1, INT_LIST_4(n2, n3, n4, n5) >
152 #define INT_LIST_6(n1, n2, n3, n4, n5, n6) multi_bit_mask::int_list_t<n1, INT_LIST_5(n2, n3, n4, n5, n6) >
153 #define INT_LIST_7(n1, n2, n3, n4, n5, n6, n7) multi_bit_mask::int_list_t<n1, INT_LIST_6(n2, n3, n4, n5, n6, n7) >
154 #define INT_LIST_8(n1, n2, n3, n4, n5, n6, n7, n8) multi_bit_mask::int_list_t<n1, INT_LIST_7(n2, n3, n4, n5, n6, n7, n8) >
155
156 }
157
158
159
sample
#include < iostream >
#include " multi_bit_mask.h "
using namespace std;
int main()
{
cout << multi_bit_mask::bit_mask < INT_LIST_1( 1 ) > ::value << endl;
cout << multi_bit_mask::bit_mask < INT_LIST_5( 0 , 1 , 2 , 3 , 4 ) > ::value << endl;
cout << multi_bit_mask::bit_mask < INT_LIST_7( 0 , 1 , 2 , 3 , 4 , 4 , 2 ) > ::value << endl;
]]>
我们先来看一个例子:
#include <boost/xpressive/xpressive.hpp>
using namespace boost::xpressive;
int main()
{
std::string hello( "hello world!" );
sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
smatch what;
if( regex_match( hello, what, rex ) )
{
std::cout << what[0] << '\n'; // whole match
std::cout << what[1] << '\n'; // first capture
std::cout << what[2] << '\n'; // second capture
}
return 0;
}
使用regex_match来用这个正则对象匹配一个串。结果储存在what?br>其中what[0]q回整个Ԍwhat[1]~what[n]q回文法中用于标记的部分(用小括号括v来的部分)
最后将输出
hello world!
hello
world
静态文法:
Xpressive除了可以用compile来分析一个文法串之外Q还可以用类gSpirit的方式来静态的指定文法Q?br>
sregex re = '$' >> +_d >> '.' >> _d >> _d;
q样定义文法比之前的动态定义更加高效,q且q有一个附加的好处Q?br>分定义Q?/p>
sregex re = '$' >> +_d >> '.' >> _d >> _d;
sregex s = '(' >> re >> ')';
通过分定义Q文法能被表C的更加清楚?br>更加的是,分定义q可以向后引用,因此能够分析EBNF
sregex group, factor, term, expression;
group = '(' >> by_ref(expression) >> ')';
factor = +_d | group;
term = factor >> *(('*' >> factor) | ('/' >> factor));
expression = term >> *(('+' >> term) | ('-' >> term));
Xpressive可以在这里下?br>http://boost-consulting.com/vault/index.php?PHPSESSID=f1d4af8b742cfa7adae7aab373cfc535&direction=0&order=&directory=Strings%20-%20Text%20Processing&PHPSESSID=f1d4af8b742cfa7adae7aab373cfc535
内有详细的文?/p>
, class CrossPolicy = AvgCrossPolicy //杂交方式
, class SelectPolicy = DefaultSelectPolicy //子代选择的方?br> , class VariationPolicy = ReverseVariationPolicy> //变异方式
class Gene
: private AvgCrossPolicy
, private SelectPolicy
, private VariationPolicy
{
....
};
甚至允许我们以Q意的序书写几个Policy参数Q都不会有问?/p>
TypeList
一个TypeList是一个类型的容器
template <typename Type_, typename Next_>
struct TypeList
{
typedef Type_ Type;
typedef Next_ Next;
};
q就是一个TypeList?br>看这个写法,是不是像一个链表?
首先定义一个类型来表示链表:class NullType{};
现在一个包含了2个类型的TypeList可以写为:
TypeList<T1, TypeList<T2, NullType> >
q个比较?br>template<class Base, class T>
class IsDerivedFrom
{
struct large{char a[2];};
static char pred(Base*);
static large pred(...);
public:
enum {Is = sizeof(pred((T*)0)) == sizeof(char)};
};
template <class List, class Base>
struct FindChild
{
template <bool IsChild>
struct Select
{
typedef typename List::Type Type;
};
struct Select<false>
{
typedef typename FindChild<typename List::Next, Base>::Type Type;
};
};
template <class Base>
struct FindChild<NullType, Base>
{
typedef NullType Type;
};
q里使用NullType来表明没扑ֈ
class SelectPolicyBase{};
class VariationPolicyBase{};
内容为空p了,q样也没有虚函数调用的开销
然后声明一个类来表C默认情况:
class DefaultPolicy{};
#define TYPELIST_3_N(a, b, c) TypeList<a, TypeList<b, TypeList<c, NullType> > >
template <class List, class Base, class DefaultType>
struct Selector
{
template <class RetType>
struct Judge
{
typedef RetType Type;
};
template<>
struct Judge<NullType>
{
typedef DefaultType Type;
};
typedef typename Judge<typename FindChild<List, Base>::Type >::Type Type;
};
, class CrossPolicy_ = DefaultPolicy
, class SelectPolicy_ = DefaultPolicy
, class VariationPolicy_ = DefaultPolicy //其后的参数用户不可指?br> , class List = TYPELIST_3_N(CrossPolicy_, SelectPolicy_, VariationPolicy_)
, class CrossPolicy = typename Selector<List, CrossPolicyBase, AvgCrossPolicy>::Type
, class SelectPolicy = typename Selector<List, SelectPolicyBase, DefaultSelectPolicy>::Type
, class VariationPolicy = typename Selector<List, VariationPolicyBase, ReverseVariationPolicy>::Type
>
class Gene
: private CrossPolicy
, private SelectPolicy
, private VariationPolicy
{
....
};
其中W?-7个参敎ͼListQCrossPolicyQSelectPolicy和VariationPolicyQ是不由用户指定的,仅仅是ؓ了v一个别?br>W一个参数T必须指定Q然?Q?Q?q?个参数就可以L的改变顺序了
例如Q可以写Gene<T, DefaultSelectPolicy, AvgCrossPolicy>而不会有M问题
如果不想要最后面几个参数的话也行Q但是代码就要稍微长一?br>而且最好在c里面进?个typedef
typedef typename Selector<List, CrossPolicyBase, AvgCrossPolicy>::Type CrossPolicy;
{,以便在实现的时候?/p>
]]>
]]>
group ::='('exp ')'
factor ::=integer| group
term ::=factor(('*'factor)|('/'factor ))*
exp ::=term(('+'term)|('-'term ))*
q是一个整数表辑ּ的EBNF。该D|q用spirit在C++中的实现则是Q?br>
rule<> group, factor, term, exp;
group = '(' >> exp >> ')';
factor = int_p | group;
term = factor >> *(('*' >> factor) | ('/' >> factor));
exp = term >> *(('+' >> term) | ('-' >> term));
q里使用=代替::=, ?gt;>代替I格q接。ƈ且由于C++语法所限,EBNF中后|的*在spirit中改为前|?br>{式左边的单词被UCؓ一个ruleQ等式右边ؓrule的定义。我们可以看Z个group是一个exp加上一ҎP一个factor是一个整数或者一个group,一个term是一个或多个factor?/q接Q一个exp是一个或多个term?-q接。处于最端的exp可以据此识别Z下表辑ּ
12345
-12345
+12345
1 + 2
1 * 2
1/2 + 3/4
1 + 2 + 3 + 4
1 * 2 * 3 * 4
(1 + 2) * (3 + 4)
(-1 + 2) * (3 + -4)
1 + ((6 * 200) - 20) / 6
(1 + (2 + (3 + (4 + 5))))
得到一个rule之后Q我们就可以?/font> parse函数对一个串q行识别了。例?br>
该函数返回一个结构parse_infoQ可以通过讉K其中的full成员来判断是否成功识别,也可以访问stop成员来获知失败的位置。这里要特别提一点,关于各个W号之间的空|spirit的文档的正文说的是给parse再传一个参数space_pQ通知parse跌所有的I格Q然而在FAQ中又提到Q如果用以上方法定义ruleQ第三个参数传space_p会失败。原因是使用rule默认定义的规则被UCؓcharacter level parsingQ即字符U别解析Q而parse的第3个参C适用于phrase level parsingQ即语法U别解析。要使用W?个参数可以有几种Ҏ?br> 1。在parse的第二个参数直接传入一个EBNF表达式,不创建rule对象?br>
2。以rule<phrase_scanner_t>创徏rule?br>
注意虽然可以用这两个办法屏蔽I格Q但是这样可能完全改变EBNF文法的语义,其是在语言本n需要识别空格的时候。对于这U情况,可以不用第三个参数Qƈ在需要出现空格的地方加上space_p,或?space_p?space_pQ其??分别表示后面的符可l出Cơ以上和0ơ以上。例如一个以I格分隔的整数列表可以写成int_p >> *(+space_p >> int_p)
如上使用parse可以识别一个串Q但q不能做更多的操作,例如语法里的各个成分提取出来。对于这L需求,可以通过actor实现。下面是使用actor的一个简单例?br>
bool
parse_numbers(char const* str, vector<double>& v)
{
return parse(str,
// Begin grammar
(
real_p[push_back_a(v)] >> *(',' >> real_p[push_back_a(v)])
)
,
// End grammar
space_p).full;
}
注意?span class=identifier>real_p后面的[]Q中括号里面是一个仿函数Q函数指针或者函数对象)Q该仿函数具有如下调用型?br>
void operator()(IterT first, IterT last) const;
void operator()(NumT val) const;
void operator()(CharT ch) const;
一旦spase发现了匹?span class=identifier>real_p的子Ԍ׃调用该functor。不同的rule可能会对应不同的调用型别?/span>
W一个型别针对一般规则,first和lastZ个指向字W的q代器(一般ؓchar*Q?匚w的子串ؓ[first, last)
W二个型别针Ҏ字型规则Q如real_p和int_p, 参数val是一个数字类型?br>W三个性别针对单字W型规则Q如space_p, 参数ch是一个字W类型?br>real_p[push_back_a(v)]中的push_back_a是一个spirit已经定义好的functorQ它会将匚w好的内容依照匚w到的旉序调用v的push_back函数加入到v中?br>
到此spirit的常用功能就都介l完了。要详细深入了解可以参考spirit的文档?br>
最后在题一个注意要炏Vspirit的各UEBNFq接都是指针q接Q因此才能在expression被赋值前在group的定义里面用。所以在使用EBNF的时候一定要心不要局部变量的rule提供l全局或者类成员变量使用Q例如:
class A
{
rule<> s;
A()
{
rule<> r = int_p | hex_p;
s = r >> *(+space_p >> r); //error, r destructed after return
}
};
如果真想使用局部作用域Q可以在局部的rule前面加上static.