Содержание

Зачем это нужно

Каждому в своей программисткой практике приходилось сталкиваться с ситуациями, когда необходимо было что-либо преобразовать из строки в, предположим, число, или обратно. В зависимости от того, что, куда и как преобразовывается, для этого можно применять sprintf/sscanf, _itoa/atoi (и другие функции из этой группы), strtoi, и т. п. Все эти методы по своему хороши, но для каждого варианта преобразования необходимо помнить - «а что лучше всего для этого преобразования подходит?» boost::lexical_cast позволяет снять эту проблему. Для его использования достаточно знать - какой тип в какой вы ходите преобразовать. И все. Например:

// преобразует целое в строку
std::string str = boost::lexical_cast<std::string>(10);
// строку в целое
int value = boost::lexical_cast<int>("10");
// преобразует пару целых в экземпляр класса Point
Point pt = boost::lexical_cast<Point>("10, 20");
// обратное преобразование
std::wstring wstr = boost::lexical_cast<std::wstring>(pt);
// и т. д.

Достаточно удобно, не правда ли?

Как это работает

Принцип работы boost::lexical_cast очень прост. Для преобразования он использует строковый поток (std::strstream), выводя (с помощью оператора «) в него преобразуемое значние, после чего читая из него значение типа, в который делается преобразование. Т. е. вызов boost::lexical_cast эквивалентен:

// положим, что from_val и to_val - это, соответственно преобразуемое
// значение и приемник результата преобразования
std::ostringstream o_str;
o_str << from_val
std::istringstream i_str(o_str.str());
i_str >> to_val;

Из этого становится очевидным, что для корректного выполнения преобразования необходимо (и достаточно) наличия для преобразуемого типа перегруженного оператора вывода в поток и/или чтения из потока. Для всех примитивных типов такие операторы реализованы в библиотеке STL, а для «пользовательских» типов такой оператор может написать сам разработчик.

Недостатки

Но не смотря на свою красоту, универсальность и соответствие общепринятым стандартам преобразования, у boost::lexical_cast есть и следущие недостатки:

  1. Низкая скорость работы. По тестам, проведенным Гербом Саттером, результаты которых он описал в своих «Новых сложных задачах на С++», boost::lexical_cast работает на порядок медленнее, чем тот же sprintf.
  2. При преобразованиях нельзя специфицировать формат желаемой или исходной строки. Т. е. преобразования выполняются в соответствии со стандартными настройками потоков.
  3. (для компилятора Visual C++) нельзя (без дополнительных телодвижений) выполнять преобразования в std::wstring/wchar_t*, если в настройках проекта не указано, что wchar_t считается встроенным типом.
  4. приведение в тип double из строкового типа, возможно лишь в том случае если в качестве разделителя (дробной части от целой) используется точка.

Достоинства

Два из трех указанных выше недостатков достаточно легко обходятся. Поскольку boost::lexical_cast - это шаблон, то достаточно несложно написать необходимую специализацию, выполняющую преобразование настолько быстро, насколько это необходимо разработчику, а также учитывающую особенности типа wchar_t в VC++.