атрибут cast в c ++ - PullRequest
       3

атрибут cast в c ++

0 голосов
/ 18 мая 2011

В моей программе я получаю строку, которая состоит из имени атрибута и значения атрибута. Например: string X 2. Моя проблема в том, что у меня много атрибутов, и они имеют разные типы. Это может быть int, логическое значение или перечисление. Например, X 2 должно быть int x = 2; STATUS 0 должно быть bool status = false и т. Д.

Так что мне нужно прочитать строку и создать атрибут со значением, которое зависит от строки. Я думал о hash_map, но, может быть, у вас есть другая идея?

Я также не знаю, как я могу поместить тип атрибута в hash_map. Примерно так:

typedef unordered_map<string, type> MapType;

Я знаю, как hash_map работает с указателем на функцию; может быть, есть что-то для типа. Это может дать мне ссылку, например, на int, bool, а затем я могу найти карту и привести значение из моей строки.

Ответы [ 5 ]

1 голос
/ 18 мая 2011

Вы можете использовать тип map<string, string> для хранения атрибутов при загрузке / чтении их из строк, таких как «X 2» или «STATUS 0».Затем напишите класс, например AttributesContainer, который действует как обертка для карты, с методами getString(string key), getInt(string key), getBoolean(string key) и т. Д.

Итак, в зависимости от вызывающего и вызываемого getМетод, вы можете интерпретировать значение из карты в зависимости от вашей предпочтительной логики.Вы можете интерпретировать 0/1 как логическое значение, если вызывается getBoolean, но возвращать int 0 или 1, если вызывается getInt.

0 голосов
/ 19 мая 2011

Не могу поверить, что я собираюсь предложить это, но здесь ...

Определите простой attribute класс, который является оберткой вокруг std::string - который является вашей ценностью.Этот класс должен предоставлять операторы преобразования (насколько мне они не нравятся, в этом случае они могут немного облегчить жизнь).

#include <iostream>
#include <boost/lexical_cast.hpp>

struct attribute
{
  std::string value;

  operator bool() const { return boost::lexical_cast<bool>(value); }
  operator int() const { return boost::lexical_cast<int>(value); }
  operator unsigned int() const { return boost::lexical_cast<unsigned int>(value); }
  operator double() const { return boost::lexical_cast<double>(value); }
  operator std::string() const { return value; }
};

int main(void)
{
  attribute a = { "foo" };
  attribute b = { "10" };

  std::string sa = a;
  int sb = b;
  unsigned int su = b;

  std::cout << sa << std::endl;
  std::cout << sb << std::endl;
  std::cout << su << std::endl;
}

Итак, здесь тип переменной, которой вы назначаете, определяетпреобразование, которое применяется.Теперь главная проблема при таком подходе заключается в том, что если нет оператора прямого преобразования, компилятор выберет наилучшее совпадение - что может не всегда быть тем, что вы хотите.Поэтому, чтобы быть в безопасности, определите все необходимые вам преобразования, и вы можете быть в порядке.

Затем сохраните этот attribute вместе с вашим строковым ключом на карте (ПРИМЕЧАНИЕ: вам нужно будет использовать ctor по умолчанию)скопируйте ctor / assign op и т. д., поскольку настройки по умолчанию небезопасны).Если вы не можете быть обеспокоены последним, сохраните умный указатель на карте, например,

std::map<std::string, boost::shared_ptr<attribute> > attributes;

Теперь ваш интерфейс должен принять ключ и вернуть attribute, например,

attribute const& get(std::string const& some_key)
{
  map<>::iterator it = attributes.find(some_key);
  return *it->second; 
}

bool bv = get(some_key); // automatically converted to bool (if lexical_cast doesn't throw)
0 голосов
/ 18 мая 2011

Может быть, вам нужно взглянуть на какую-нибудь библиотеку c ++ JSON (анализатор) , чтобы решить вашу проблему.

0 голосов
/ 18 мая 2011

Это можно сделать с помощью шаблона Factory , но для этого вам потребуется корневой класс. Например, как фабрика возвращает указатель на string или указатель на bool?

Как используются эти объекты?

Другое предложение состоит в том, чтобы иметь vector для каждого типа объекта и два std::map контейнера, один для функций для создания объектов и другой для указателей на функции создания. Используйте одну из карт, чтобы получить функцию для создания предмета. Используйте другую карту, чтобы получить вектор для элемента. Выполнить функцию с передачей правильного вектора.

В противном случае, это указатели на void.

0 голосов
/ 18 мая 2011

Получение значений различных типов (логическое, целое, строковое ...) из конфигурационного файла или что-то такое - это проблема, которая уже решалась много раз ... может быть, слишком много раз:)

Естьпосмотрите, как это делается на Boost.Program_options , cfgparser , IniReader , ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...