利用“宏元编程”解决重复问题
来源:互联网 发布:如何做淘宝优惠券网站 编辑:程序博客网 时间:2024/06/13 20:57
在一个网元中,存在着各种“受管对象”(Managed Object)。每种“受管对象”都有自己的一组配置数据。比如,一个“学生”对象的配置数据定义如下:
struct Student{ unsigned long code; char name[9]; unsigned char height; unsigned short score;};
在“受管对象”配置修改的过程中,如果出了差错,应该可以将配置“回滚”到之前的值。所以,我们定义了如下模版来保存一个配置项。
template <typename T>struct ConfigValue{ ConfigValue(const T& defaultValue) : changed(false) , currentValue(defaultValue) , oldValue(defaultValue) {} void set(const T& value) { if(currentValue == value) return; oldValue = currentValue; currentValue = value; changed = true; } const T& get() const { return currentValue; } const T& getOldValue() const { return changed ? oldValue : currentValue; } void resetStatus() { changed = false; } void revert() { if(not changed) return; currentValue = oldValue; changed = false; } bool isChanged() const { return changed; }private: bool changed; T currentValue; T oldValue;};基于此模版,我们将“学生”的配置定义为:
struct StudentConfig{ ConfigValue<unsigned long> code; ConfigValue<FixedSizeString<8> > name; ConfigValue<unsigned char> height; ConfigValue<unsigned short> score;};通过SNMP的客户端,用户可以一次性修改某个“受管对象”的多个配置数据。比如,对于某个“学生”对象,用户可以同时修改他的“身高”和“总成绩”。所以我们定义了如下模版来保存由SNMP客户端而来的某个配置项:
template <typename T>struct OptionalConfigValue{ OptionalConfigValue() : specified(false) {} void set(const T& value) { this->value = value; specified = true; } void updateTo(ConfigValue<T>& config) const { if(specified) config.set(value); }private: bool specified; T value;};以“学生”对象为例,相应的SNMP配置结构则定义为:
struct StudentOptionalConfig{ OptionalConfigValue<unsigned long> code; OptionalConfigValue<FixedSizeString<8> > name; OptionalConfigValue<unsigned char> height; OptionalConfigValue<unsigned short> score;};这样,StudentConfig应该提供一个update接口,来更新来自于SNMP客户端的配置数据。比如:
struct StudentConfig{ StudentConfig() : code(0) , name("anon") , height(170) , score(0) {} void update(const StudentOptionalConfig& config) { config.code.updateTo(code); config.name.updateTo(name); config.height.updateTo(height); config.score.updateTo(score); } void revert() { code.revert(); name.revert(); height.revert(); score.revert(); } void configDone() { code.resetStatus(); name.resetStatus(); height.resetStatus(); score.resetStatus(); }private: ConfigValue<unsigned long> code; ConfigValue<FixedSizeString<8> > name; ConfigValue<unsigned char> height; ConfigValue<unsigned short> score;};从上述的实现中,我们能够发现强烈的重复模式:首先,所有的配置信息在不同的地方重复出现,其次,对于不同的配置信息进行相同的处理。
为了解决这样的重复问题,我们首先使用宏来定义“元数据”:
// Student.hDEFINE_CONFIG (code, unsigned long, 0)DEFINE_CONFIG (height, unsigned char, 170)DEFINE_CONFIG (score, unsigned short, 0)DEFINE_STR_CONFIG(name, 8, "anon")
而“魔法”的关键在于,如何来通过不同的宏定义来“解释”这些元数据。
比如,对于StudentOptionalConfig的定义,我们可以将其代码转化为:
// StudentOptionalConfig.hstruct StudentOptionalConfig{#include <OptionalConfigDef.h>#include "Student.h"};而OptionalConfig.h的定义为:
// OptionalConfigDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ OptionalConfigValue<type> name;////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ OptionalConfigValue<FixedSizeString<size> > name;类似的,StudentConfig的定义则变为:
// StudentConfig.hstruct StudentConfig{ StudentConfig() : #include <DefaultValueDef.h> #include "Student.h" , dummy(true) {} void update(const StudentOptionalConfig& config) { #include <UpdateDef.h> #include "Student.h" } void revert() { #include <RevertDef.h> #include "Student.h" } void configDone() { #include <ConfigDoneDef.h> #include "Student.h" }private: #include <ConfigDef.h> #include "Student.h" bool dummy;};而各个魔法头文件的定义分别为:
// DefaultValueDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ name(defaultValue),////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ name(defaultValue),
// UpdateDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ config.name.updateTo(name);////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ config.name.updateTo(name);
// CofigDoneDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ name.resetStatus();////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ name.resetStatus();
// RevertDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ name.revert();////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ name.revert();
// ConfigDef.h////////////////////////////////////////////////#ifdef DEFINE_CONFIG#undef DEFINE_CONFIG#endif#define DEFINE_CONFIG(name, type, defaultValue) \ ConfigValue<type> name;////////////////////////////////////////////////#ifdef DEFINE_STR_CONFIG#undef DEFINE_STR_CONFIG#endif#define DEFINE_STR_CONFIG(name, size, defaultValue) \ ConfigValue<FixedSizeString<size> > name;有了这些魔法定义文件,每个配置定义文件就呈现除了简单一致的规则,很容易就可以写出一个代码生成器,自动生成相关的代码。下面是一个Python的实现:
import sysoptional_config_template = '''#ifndef __%s_OPTIONAL_CONFIG_H__#define __%s_OPTIONAL_CONFIG_H__struct %sOptionalConfig{ #include <OptionalConfigDef.h> #include "%s.h" };#endif'''config_template = '''#ifndef __%s_CONFIG_H__#define __%s_CONFIG_H__struct %sConfig{ %sConfig() #include <DefaultValueDef.h> #include "%s.h" dummy(true) {} void update(const %sOptionalConfig& config) { #include <UpdateDef.h> #include "%s.h" } void configDone() { #include <ConfigDoneDef.h> #include "%s.h" } void revert() { #include <RevertDef.h> #include "%s.h" }private: #include <ConfigDef.h> #include "%s.h" bool dummy;};#endif'''def write_file(name, suffix, content) : file = open(name + suffix + ".h", "w") file.write(content) file.close()def generate_optional_config(name) : write_file(name, "OptionalConfig", \ optional_config_template % \ ( name.upper(), name.upper(), name, name))def generate_config(name) : write_file(name, "Config", \ config_template % \ ( name.upper(), name.upper() \ , name, name, name, name, name, name, name, name))def generate(name) : generate_optional_config(name) generate_config(name)def usage() : print "usage: python config-gen.py config-name"if __name__ == "__main__": if len(sys.argv) != 2: usage() sys.exit(1) generate(sys.argv[1])
- 利用“宏元编程”解决重复问题
- 利用session解决重复提交的问题
- 利用Token机制解决重复重复提交问题
- 利用匿名namespace解决C++中重复定义的问题
- struts2利用拦截器解决重复提交问题
- 利用匿名namespace解决C++中重复定义的问题
- 利用分段式深度解决特效重复叠加的问题
- 利用单例模式,解决toast重复弹出的问题
- 宏元编程——技术——解决重入引起展开失败问题
- ruby元编程 消除重复代码
- 利用maven工具解决jar包冲突问题或重复加载问题
- 利用maven工具解决jar包冲突问题或重复加载问题
- 利用位运算解决排序问题(摘自编程珠玑)
- STRUTS中利用同步令牌(Token)解决重复提交的问题(转载)
- Struts中利用同步令牌(Token)解决重复提交的问题
- 利用struts的Token机制解决重复提交问题的分析
- 利用struts的Token机制解决重复提交问题的分析
- 利用xcode snippet 解决代码块重复敲写的问题
- 配置Smarty
- js常识
- 110703 ~ 110709
- Android 对话框【Dialog】去除白色边框代码
- 结构体内存字节对齐
- 利用“宏元编程”解决重复问题
- Android Dialog用法总结
- SELECT的结果中出现"乱码"的解决方案--【叶子】
- 在Android的webview中定制js的alert,confirm和prompt对话框的方法
- C/C++语言void及void指针深层探索
- 自然数拆分(tyvj1171)
- 额,突然进到博客,看见风格变了
- 如何在android手机项目中加入广告
- 视频编码部分定义