本文简单写了个 c++ 装饰器
主要使用的是c++ lamda 表达式
结合完美转发技巧,在一定程度上提升性能
实例一介绍了一个相对通用的例子
实例二:场景是这样的, 我们希望统计某项工作的耗时, 但是不想修改相关的代码
这时候装饰器就可以登场了, 装饰关系如下, 左边的被右边的装饰, 这个和 java spring 面向切面编程有些相似;
time_beign 被装饰 -> work 被装饰-> time_end 被装饰 -> time_cost
通用代码一
#define FieldSetter(name, type, field) \
type field; \
name() {} \
name(const type& field): field(field) { \
cout << "[左值 " << field << "]" << endl; \
} \
name(const type&& field) : field(move(field)){ \
cout << "[右值 " << field << "]" << endl; \
} \
name(const name& other) { \
field = other.field; \
cout << "[左值 " << other.field << "]" << endl; \
} \
name(const name&& other) { \
field = move(other.field); \
cout << "[右值 " << other.field << "]" << endl; \
}
struct ObjectField {
FieldSetter(ObjectField, string, name);
};
struct AgeField {
FieldSetter(AgeField, int, age);
};
struct SexField {
FieldSetter(SexField, string, sex);
};
void DecoratorTest() {
auto Object = [](auto ob) {
cout << ob.name << endl;
};
auto Age = [](auto age) {
cout << age.age << endl;
};
auto sex = [](auto sex) {
cout << sex.sex << endl;
};
auto withDecorator = [](auto &&head, auto &&tail, auto &&...hargs) {
head(forward<decltype(hargs)>(hargs)...);
return [f = std::move(tail)](auto &&...args) {
return f(forward<decltype(args)>(args)...);
};
};
auto nameWithAge = withDecorator(Object, Age, ObjectField("nic"));
auto withDecoratorWithSex = withDecorator(nameWithAge, sex, AgeField(18));
withDecoratorWithSex(SexField("man"));
}
int main() {
DecoratorTest();
}
输出
对输出的解释
[左值 ] 表示传参的过程中调用了拷贝构造函数
[右值 ] 表示在传参过程中调用的是 移动构造函数
测试用例二
auto withDecorator = [](auto &&head, auto &&tail, auto &&...hargs) {
return [&,f = std::move(tail)](auto &&...args) {
head(forward<decltype(hargs)>(hargs)...);
return f(forward<decltype(args)>(args)...);
};
};
long Now() {
struct timeval s;
gettimeofday(&s, NULL);
return s.tv_sec * 1e6 + s.tv_usec;
}
struct TimeElapse {
long before;
long after;
};
auto timeBegin = [](TimeElapse &ts) {
cout << "time begin" << endl;
ts.before = Now();
};
auto work = [](auto &&...strs) {
if (sizeof ...(strs) == 0) {
return;
}
cout << "work: ";
(cout << ... << strs);
cout << endl;
};
auto timeEnd = [](TimeElapse &ts) {
cout << "time end" << endl;
ts.after = Now();
};
auto timeCost = [](TimeElapse &ts) {
cout << "total cost " << ts.after - ts.before << endl;
};
int main() {
TimeElapse ts;
auto tb = withDecorator(timeBegin, work, ts);
auto te = withDecorator(tb, timeEnd, 1, 2, 3, 4, 5, 6, 7, 8);
auto tc = withDecorator(te, timeCost, ts);
tc(ts);
}