手机网站弹出层插件有哪些,做网站注意,网站域名申请,高端网站建设公司费用文章目录 p12#xff1a;复杂类型解析一、方法函数二、结果展示 p13#xff1a;复杂类型解析完善一、方法函数二、结果展示 p14#xff1a;自定义类型解析一、方法函数二、小结 p12#xff1a;复杂类型解析
本节内容主要针对完了配置类中对于复杂类型的转换。之前只实现… 文章目录 p12复杂类型解析一、方法函数二、结果展示 p13复杂类型解析完善一、方法函数二、结果展示 p14自定义类型解析一、方法函数二、小结 p12复杂类型解析
本节内容主要针对完了配置类中对于复杂类型的转换。之前只实现了基础类型之间的转换而对于容器等复杂类型无法转换所以本节实现了对于vector与string之间的转换方式。
一、方法函数
ConfigVar
之前由于只有基础类型转换代码里面直接调用lexical_cast这样做无法在传入复杂类型时进行解析。因此把lexical_cast的转化过程函数化方便在外部针对特定类型的转化。
templateclass T, class FromStr LexicalCaststd::string, T, class ToStr LexicalCastT, std::string
class ConfigVar : public ConfigvarBase {
public:typedef std::shared_ptrConfigVar ptr;ConfigVar(const std::string name, const T default_value, const std::string description ) // 初始化配置名称、参数值以及参数描述:ConfigvarBase(name,description),m_val(default_value) {}std::string toString() override { // 将参数值转换为string类型try {// return boost::lexical_caststd::string(m_val);return ToStr()(m_val);} catch(std::exception e) {SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) ConfigVar::toString exception e.what() convert: typeid(m_val).name() to string;}return ;}bool fromString(const std::string val) override { // 从string转换为参数值try {// m_val boost::lexical_castT(val);setValue(FromStr()(val));} catch (std::exception e) {SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) ConfigVar::fromString exception e.what() convert: string to typeid(m_val).name();}return false;}const T getValue() const { return m_val; }void setValue(const T v) { m_val v; }private:T m_val;
};LexicalCast
如果是int float等基础类型转化使用下列函数
// 基础类型转换 把F转换成T类型
templateclass F, class T
class LexicalCast {
public:T operator()(const F v) {return boost::lexical_castT(v);}
}; [string - vector]。代码比较清楚直接看注释就行。
// 复杂类型转换 偏特化[string - vector]
templateclass T
class LexicalCaststd::string, std::vectorT {
public:std::vectorT operator()(const std::string v) {// 调用YAML中的load函数接收一个string类型输入将其转换成node结构YAML::Node node YAML::Load(v);std::vectorT vec; // 定义结果vecstd::stringstream ss; // 使用字符串流来获取node中的每个string值for(size_t i 0; i node.size(); i) {ss.str();ss node[i];vec.push_back(LexicalCaststd::string, T()(ss.str())); // 这里相当于调用基础类型转换如果传入的vec里面元素是int类型那么就是string - int}return vec;}
};[vector - string]
// 复杂类型转换 偏特化[vector - string]
templateclass T
class LexicalCaststd::vectorT, std::string {
public:std::string operator()(const std::vectorT v) {// 定义一个node容器YAML::Node node;for(auto i : v) {node.push_back(YAML::Load(LexicalCastT, std::string()(i))); // 基础类型转换}std::stringstream ss;ss node;return ss.str();}
};二、结果展示
下面代自定义了一个配置参数项g_vec_value_config输出后载入log.yml文件更改了g_vec_value_config里面的元素值。 sylar::ConfigVarstd::vectorint::ptr g_vec_value_config sylar::Config::Lookup(system.vec, std::vectorint{1,2,3}, system vec);
void test_config() {// SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) before: g_int_value_config-getValue(); // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) before: g_float_value_config-toString();auto v g_vec_value_config-getValue();auto res g_vec_value_config-toString();std::cout res std::endl;for(auto i : v) {SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) before: i;}YAML::Node root YAML::LoadFile(/root/Web-learning/sylar/bin/conf/log.yml);sylar::Config::LoadFromYaml(root);v g_vec_value_config-getValue();for(auto i : v) {SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) after: i;}// SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) after: g_int_value_config-getValue(); // SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) after: g_float_value_config-toString();
}int main(int argc, char** argv) {// test_yaml();test_config();return 0;
}p13复杂类型解析完善
本节内容是对上一节STL容器的完善新增了对list、map、set、unordered_map、unordered_set的支持。由于本节的代码内容和上一节比较重复所以简单记录一下部分内容。
一、方法函数
map
注意循环的迭代方式与vector等容器不同然后目前对于map里面的类型只支持基本类型的转换所以后期需要按我们目前做的方式让map里面的内容支持复杂类型。
templateclass T
class LexicalCaststd::string, std::mapstd::string, T {
public:std::mapstd::string, T operator()(const std::string v) {YAML::Node node YAML::Load(v);std::mapstd::string,T vec; for(auto it node.begin(); it ! node.end(); it) {ss.str();ss it-second;vec.insert(std::make_pair(it-first.Scalar(), LexicalCaststd::string, T()(ss.str()))); }return vec;}
};宏定义
测试时代码重复比较大通过下面两个宏函数简化。
#define XX(g_var,name,prefix) \{ \auto v g_var-getValue(); \for(auto i : v) { \SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) #prefix #name : i; \} \}#define XX_M(g_var,name,prefix) \{ \auto v g_var-getValue(); \for(auto i : v) { \SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) #prefix #name : { i.first : i.second }; \} \}二、结果展示 p14自定义类型解析
本节内容主要讲解了Config解析自定义类型和上面两节一样处理复杂类型或者自定义类型的关键是片特化函数LexicalCast下面是一些简单比较记录。
一、方法函数
之前代码在解析yml文件时如果遇到相同key但是类型不同会直接忽略。比如下列代码keysystem.port的值存在两种类型当我们使用Config::Lookup(system.port)查找时不知道最后找到的是谁所以程序应该在这里报错提示。
sylar::ConfigVarint::ptr g_int_value_config sylar::Config::Lookup(system.port, (int)8080, system port);sylar::ConfigVarfloat::ptr g_int_valuex_config sylar::Config::Lookup(system.port, (float)8080, system port);Lookup
对该函数进行修改核心思想就是利用dynamic_pointer_cast如果相同key的类型不同则会转换失败返回nullptr
auto it s_datas.find(name); // 直接从配置容器中查找if(it ! s_datas.end()) {auto tmp std::dynamic_pointer_castConfigVarT(it-second);if(tmp) {SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) Lookup name name exists; } else {SYLAR_LOG_ERROR(SYLAR_LOG_ROOT()) Lookup name name exists but type not typeid(T).name(); return nullptr;}}再次运行可以看到已经有了报错提示 自定义类型
以下我们定义了一个Person类希望能从log.yml文件中解析出相应的配置项。
class Person {
public:std::string m_name;int m_age 0;bool m_sex 0;std::string toString() const {std::stringstream ss;ss [Person name m_name age m_age sex m_sex ];return ss.str();}
}; 第一步肯定是去书写对应的片特化函数LexicalCast函数里面的内容无非就是YAML::NODE类型与自定义类型之间的值传递。
namespace sylar {
// 复杂类型转换 偏特化[string - Person]
template
class LexicalCaststd::string, Person {
public:Person operator()(const std::string v) {// 调用YAML中的load函数接收一个string类型输入将其转换成node结构YAML::Node node YAML::Load(v);Person p;p.m_name node[name].asstd::string();p.m_age node[age].asint();p.m_sex node[sex].asbool();return p;}
};// 复杂类型转换 偏特化[Person - string]
template
class LexicalCastPerson, std::string {
public:std::string operator()(const Person p) {// 定义一个node容器YAML::Node node;node[name] p.m_name;node[age] p.m_age;node[sex] p.m_sex;std::stringstream ss;ss node;return ss.str();}
};
} 来一个测试用例
// 1.自定义类型
sylar::ConfigVarPerson::ptr g_person sylar::Config::Lookup(class.person, Person(), system person);// log.yml
class:person:name: ikunage: 25sex: true 输出结果 自定义类型与STL的嵌套
设计一些复杂的用例
// 2.自定义类型与STL嵌套
sylar::ConfigVarstd::mapstd::string, Person::ptr g_person_map sylar::Config::Lookup(class.map, std::mapstd::string, Person(), system map);
// 3.更加复杂的类型mapstring,vectorPerson
sylar::ConfigVarstd::mapstd::string, std::vectorPerson::ptr g_person_vec_map sylar::Config::Lookup(class.vec_map, std::mapstd::string, std::vectorPerson(), system vec_map);
// log.yml
map:person1:name: ikun2age: 252sex: trueperson2:name: ikun3age: 152sex: falsevec_map:vec1:- name: ikunage: 25sex: true- name: ikun2age: 252sex: truevec2:- name: ikun4age: 225sex: true- name: ikun21age: 2152sex: true输出结果 二、小结
整个配置模块到这基本完成这几节的内容目的就是尽可能的去解析不同类型的配置内容所以只要12节视频基本弄懂后面两节的内容也没什么大问题。建议自己跟着视频写好代码后可以把解析过程每一步的内容打印出来看和自己想的是否一样。