1

我一直在使用我编写的一个类(这是一个有效的缩减版本),它提供了一种从字符串加载和保存任何变量的方法,并且可以添加到类中,前提是类中有这个对象并且它称为_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(&parameter)));

  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;
  }
}
4

2 回答 2

0

这称为序列化或数据编组。在类中添加序列化和反序列化方法是很常见的。例如,Python 有“pickle”作为将数据对象序列化为二进制格式的一种方式——这正是你正在做的。

一些更好的序列化格式(恕我直言):

  • (Google) ProtocolBuffers - 二进制,做你想做的,可用于 C++,有 IDL
  • JSON - 广泛使用/实现的跨语言
  • BJSON - 二进制 json 格式(参见 MongoDB 等)
  • MessagePack - 另一种二进制 json 格式,可能比 BJSON 更好
  • UBJSON - 这可能是最好的二进制 json 格式
  • xupl - 这似乎也是一种很棒的格式
  • XDR - 比 JSON 格式稍旧,但非常好
  • Pickle - 它特定于 Python,但其他语言有 pickle 库

Ruby 使用 .to_s (toString) 扩充对象以启用打印。遵循同样的模式,将方法添加到您的类中 .serialize 和 .deserialize 方法可以满足您的需求。并且使用 JSON 或 IDL 会给你一些更接近你所寻求的多态反序列化的东西。请记住,JSON 宣布成员名称,而 IDL 的用途大致相同。

于 2013-10-05T00:38:19.690 回答
0

根据项目的范围,您应该考虑开始使用代码生成器,而不是使用 c++ 语言工具解决问题。有几个非常好的项目可以解决比您描述的问题更多的问题:

例如:Google 协议缓冲区、Apache thrifty 等等

于 2013-10-04T21:44:25.117 回答