我一直在使用我编写的一个类(这里是一个可以工作的精简版本),它提供了一个方法来加载和保存字符串中的任何变量,并且可以添加到这个类中,前提是该类中有这个对象,并且名为_settings_loader。每个变量都是通过#define ADD_PARAMETER(x) _settings_loader.AddParameter(#x,x);宏添加的。
我希望有人能建议一种更简单的方法来扩展它,而不是为每种类型使用每个单独的案例?我知道C++是类型定义的,但是我之前尝试做的事情已经完成了(我不想在添加每个变量时使用模板)。
标题
#pragma once
#include <boost/any.hpp>
#include <map>
#include <string>
#include <iostream>
#include <vector>
#define ADD_PARAMETER(x) _settings_loader.AddParameter(#x, x);
class SettingsLoader
{
public:
SettingsLoader();
template <class T> void AddParameter(std::string name, T & parameter);
void SetParameter(std::string name, std::string value);
std::string GetParameterValue(std::string name);
void PrintOutParameters();
std::vector<std::pair<std::string, std::string> > GetAllParametersAsStrings();
protected:
std::map<std::string, boost::any> _parameters;
bool _debug;
};
template <class T> void SettingsLoader::AddParameter(std::string name, T & parameter)
{
_parameters.insert(std::make_pair(name, boost::any(¶meter)));
if (_debug)
{
std::cout << "Added parameter " << name << std::endl;
}
}CPP
#include "settingsloader.h"
#include <boost/lexical_cast.hpp>
SettingsLoader::SettingsLoader():
_parameters(),
_debug(false)
{
}
void SettingsLoader::SetParameter(std::string name, std::string value)
{
try
{
std::map<std::string, boost::any>::iterator itterator = _parameters.find(name);
if (itterator != _parameters.end())
{
boost::any boost_any = itterator->second;
if (boost::any_cast<double*>(boost_any))
{
double * value_to_set = boost::any_cast<double*>(boost_any);
*value_to_set = boost::lexical_cast<double>(value);
}
else if (boost::any_cast<int*>(boost_any))
{
int * value_to_set = boost::any_cast<int*>(boost_any);
*value_to_set = boost::lexical_cast<int>(value);
}
else if (boost::any_cast<long*>(boost_any))
{
long * value_to_set = boost::any_cast<long*>(boost_any);
*value_to_set = boost::lexical_cast<long>(value);
}
}
else
{
if (_debug)
{
std::cout << "Parameter " << name << " could not be set" << std::endl;
}
}
}
catch(...)
{
}
}
std::string SettingsLoader::GetParameterValue(std::string name)
{
try
{
std::map<std::string, boost::any>::iterator itterator = _parameters.find(name);
if (itterator != _parameters.end())
{
boost::any boost_any = itterator->second;
if (boost::any_cast<double*>(boost_any))
{
double * value_to_get = boost::any_cast<double*>(boost_any);
return boost::lexical_cast<std::string>(*value_to_get);
}
if (boost::any_cast<int*>(boost_any))
{
int * value_to_get = boost::any_cast<int*>(boost_any);
return boost::lexical_cast<std::string>(*value_to_get);
}
if (boost::any_cast<long*>(boost_any))
{
long * value_to_get = boost::any_cast<long*>(boost_any);
return boost::lexical_cast<std::string>(*value_to_get);
}
}
}
catch(...)
{
}
return "";
}
std::vector<std::pair<std::string, std::string> > SettingsLoader::GetAllParametersAsStrings()
{
std::vector<std::pair<std::string, std::string>> output_vector;
for (auto pair : _parameters)
{
output_vector.push_back(std::make_pair(pair.first, GetParameterValue(pair.first)));
}
return output_vector;
}
void SettingsLoader::PrintOutParameters()
{
std::cout << "+=======================+" << std::endl
<< "|Printing out parameters|" << std::endl
<< "+=======================+" << std::endl;
std::vector<std::pair<std::string, std::string>> names_and_values = GetAllParametersAsStrings();
for (std::pair<std::string, std::string> pair : names_and_values)
{
std::cout << pair.first << " = " << pair.second << std::endl;
}
}发布于 2013-10-05 05:44:25
根据项目的范围,您应该考虑开始使用代码生成器,而不是使用c++语言工具来解决问题。有几个非常好的项目可以解决比你描述的问题多得多的问题:
例如: Google protocol buffers,Apache thrifty和其他许多
发布于 2013-10-05 08:38:20
这称为序列化或数据编组。向您的类添加序列化和反序列化方法也是很常见的。例如,Python将“pickle”作为一种将数据对象序列化为二进制格式的方法--这正是您正在做的事情。
一些更好的序列化格式(IMHO):
H111xupl-这似乎也是一个很好的格式<代码>H212<代码>XDR-比JSON格式稍早,但非常好<代码>H214<代码>H115 pickle -它是特定于Python的,但其他语言有泡菜库<代码>H216<代码>F217
Ruby使用.to_s (toString)增强对象以启用打印。遵循同样的模式,将方法添加到您的类中,将.serialize方法添加到您的类中,并将.deserialize方法添加到您的类中,就可以得到您想要的大部分内容。使用JSON或IDL将使您更接近您所寻求的多态反序列化。请记住,JSON宣布成员名称,而IDL的目的大致相同。
https://stackoverflow.com/questions/19191110
复制相似问题