Comments 46
А почему изобретён велосипед для логгинга? Ведь есть же log4cpp.
Так в том то и дело, что если вы используете POCO, то вам не нужно обременять себя заботой о ведении проекта с дополнительными библиотеками. Как следствие отпадает необходимость в обновлении, перекомпилировании.
Боже упаси юзать log4cpp, куда лучше boost.log или glog
Legacy code :(
Ещё очень неплох log4cplus
Какие ваши критерии по выбору библиотеки логирования?
Я рассматривал следующие критерии:
— Конфигурации логирования без перекомпиляции приложения. Возможность переконфигурации уже запущенного приложения «на лету»
— Поддержка многопоточности
— Возможность вывода в stdout/stderr/file/debug output/console/… Возможность асинхронного логирования
— Возможность настройки формата вывода лога
— «Хорошая» лицензия
— Кроссплатформенность + поддержка VS 2010
— Библиотека не «заброшена»
— Поддержка нескольких уровней логирования
— (желательно) наличие stream-like интерфейса (как при выводе в std::ostream)
Под них хорошо подходили log4cplus, и POCO::Logging. В итоге остановились на первом (не хотелось тянуть всю библиотеку только ради логирования)
— Конфигурации логирования без перекомпиляции приложения. Возможность переконфигурации уже запущенного приложения «на лету»
— Поддержка многопоточности
— Возможность вывода в stdout/stderr/file/debug output/console/… Возможность асинхронного логирования
— Возможность настройки формата вывода лога
— «Хорошая» лицензия
— Кроссплатформенность + поддержка VS 2010
— Библиотека не «заброшена»
— Поддержка нескольких уровней логирования
— (желательно) наличие stream-like интерфейса (как при выводе в std::ostream)
Под них хорошо подходили log4cplus, и POCO::Logging. В итоге остановились на первом (не хотелось тянуть всю библиотеку только ради логирования)
std::string text = config().getString("Group.ValueText"); // text == "Hello world"
int value = config().getInt("Group.IntValue"); // value == 123
Ну что за адЪ? Почему нельзя было сделать
auto text = config().value("Group.ValueText", "Some default text");
auto int = config().value("Group.IntValue", 100500);
?
А такая жёсткая привязка к C++0х разве не противопоказана библиотеке широкого применения?
Вопрос стоит скорей, возможно ли использовать такой код в рамках стандарта C++03 и без RTTI
И насколько данный код будет производителен.
string text = config().value("Group.ValueText");
int integ = config().value("Group.IntValue");
И насколько данный код будет производителен.
И к тому же возможны преобразование Int -> string, но не всегда наоборот (ваш К.О.)
А вы не поняли кода просто
А там уж или преобразование типа Any в нужный тип делать или специализировать для int, std::string, const char * и так далее. Скорость будет точно такой же как и в случае с кучей stringValue, intValue, а объем кода заметно меньше и апи чище.
template <typename T>
T Config::value(const std::string &key, const T &defValue);
А там уж или преобразование типа Any в нужный тип делать или специализировать для int, std::string, const char * и так далее. Скорость будет точно такой же как и в случае с кучей stringValue, intValue, а объем кода заметно меньше и апи чище.
Только там не Any, разработчики решили не связываться с RTTI, наверняка поэтому такая «красота».
Однако ваш метод имеет право на жизнь, можно отправить предложение разработчикам.
Однако ваш метод имеет право на жизнь, можно отправить предложение разработчикам.
Если возникнет необходимость различать, например, int и char, то придется писать что-то вроде
А еще когда вы пишете «stringValue», код более читабельный: сразу видно, какой тип вы ожидаете на выходе. А в вашем варианте сразу это поймет только человек, который знаком с функцией value и знает, что ее тип зависит от типа второго аргумента. По умолчанию это неочевидно.
Я не утверждаю, что ваш вариант хуже. Я считаю, в каждом из них есть плюсы и минусы. А мне больше всего нравится вариант, реализованный в Qt: функция QSettings::value возвращает объект псевдодинамического типа QVariant, который затем может быть преобразован к нужному типу с помощью toString(), toInt() и т.д. Кстати, в Poco вроде есть аналог этого типа.
value(key, (char) 1)
, это получается более громоздко, чем charValue(key)
. К тому же приведение типов может сработать очень неочевидно и привести к неожиданным последствиям, а в коде будет выглядеть вполне правдоподобно. Ярким пример тому — функция QString::arg, значение которой может разительно изменяться в зависимости от того, передали вы 'x' или QChar('x'). Поэтому рассматривать перегрузку метода как панацею не стоит. А еще когда вы пишете «stringValue», код более читабельный: сразу видно, какой тип вы ожидаете на выходе. А в вашем варианте сразу это поймет только человек, который знаком с функцией value и знает, что ее тип зависит от типа второго аргумента. По умолчанию это неочевидно.
Я не утверждаю, что ваш вариант хуже. Я считаю, в каждом из них есть плюсы и минусы. А мне больше всего нравится вариант, реализованный в Qt: функция QSettings::value возвращает объект псевдодинамического типа QVariant, который затем может быть преобразован к нужному типу с помощью toString(), toInt() и т.д. Кстати, в Poco вроде есть аналог этого типа.
> auto int = config().value(«Group.IntValue», 100500);
Меня все больше и больше страшат нововведения в стандарт C++.
Что сия команда значит?
Меня все больше и больше страшат нововведения в стандарт C++.
Что сия команда значит?
auto intA = config().value(«Group.IntValue», 100500);
//Все довольно таки просто:
//config().value(«Group.IntValue», 100500) - вернет int, в соотв. с типом 2ой переменной
//при инициализации intA примет тип rvalue, то есть int
//данная декларация аналогична
int intA = config().value(«Group.IntValue», 100500);
Как же задолбала эта КДПВ!
Что ни статья на околодевовскую тематику, так обязательно в ней этот дом на курьих ножках :)
Что ни статья на околодевовскую тематику, так обязательно в ней этот дом на курьих ножках :)
Программирование на XML. Теперь и в C++.
Сами эти POCO не во всем придерживаются того что придумали. Соглассно их кодинг-стайлу: строчка из poco-1.4.3p1\Net\src\NameValueCollection.cpp:
должна быть совершенно другой:
Странно. Вроде дядьки умные, а почему-то не юзают то что сами и разрабатывают!
const std::string& NameValueCollection::get(const std::string& name, const std::string& defaultValue) const
{
должна быть совершенно другой:
const std::string& NameValueCollection::get(
const std::string& name,
const std::string& defaultValue) const
{
Странно. Вроде дядьки умные, а почему-то не юзают то что сами и разрабатывают!
Класс! Следующее же мелкое приложение напишу с POCO, столько всяких мелких вкусностей, которые раньше руками приходилось делать или собирать: glog, TCLAP (аргумент командной строки) и прочее.
Спасибо!
Спасибо!
Добро пожаловать на темную сторону.
Наоборот, светлая сторона просвещения. Темная сторона с++ это как раз сильная разрозненность библиотек и подходов. Стандартизация, хотя бы де-факто, базовых возможностей — это хорошо. Не нужно изобретать логгер каждый раз. Был бы стандартный — 90% разработчиков бы пользовались. Так же и со всякими приведенными в посте остальными вещами.
Ну судя по описанию, это хоть и хорошая библиотека, но в значительной степени пересекается с boost, при этом уступая ей в гибкости. И boost куда ближе к «стандартной», собственно он начался с библиотеки модулей, которые не попали в страндарт, а часть модулей легли в основу C++11
Хотите стандартизацию дефакто, юзайте Qt или буст на крайняк, а про остальное забудьте
Qt я так и не трогал — мне не нравится этот дополнительный компилятор.
буст конечно использую, это же мейнстрим — что сегодня в бусте, завтра в стандарте, ну или и завтра в бусте, но все так же де факто считают его стандартом.
Ну поко миленький и довольно известный. Еще из известных слышал про ACE и ICU (для юникода, юзал, умеет все, что только можно представить, ибо это и есть реализация стандарта юникода)
буст конечно использую, это же мейнстрим — что сегодня в бусте, завтра в стандарте, ну или и завтра в бусте, но все так же де факто считают его стандартом.
Ну поко миленький и довольно известный. Еще из известных слышал про ACE и ICU (для юникода, юзал, умеет все, что только можно представить, ибо это и есть реализация стандарта юникода)
Я отказался от TCLAP в пользу boost.program_options и не жалею! )
Ну это если вы тянете буст. На тот момент я не тянул, там был небольшой проект, но с кучей опций. Зато он header-only, что сильно выделяло его на фоне всех остальных библиотек.
>>На тот момент я не тянул
Что вы вкладываете в эти слова? Не знание?
>>Зато он header-only
Буст солидной частью тоже в хидер-онли
Что вы вкладываете в эти слова? Не знание?
>>Зато он header-only
Буст солидной частью тоже в хидер-онли
Не изпользовал. Это в некотором смысле была лабараторная и была острая необходимость, чтобы проект суммарно занимал несколько мегабайт. Я знаю, что можно с помощью bcp отобрать только нужные хедеры из буста, но там такие зависимости, что даже самый незначительный shared_ptr тянет 3 мб сорцов.
>> Буст солидной частью тоже в хидер-онли
бесспорно, но про program_options я не знаю, а там бывает, что на ровном месте библиотека требует компиляции. boost filesystem, например.
>> Буст солидной частью тоже в хидер-онли
бесспорно, но про program_options я не знаю, а там бывает, что на ровном месте библиотека требует компиляции. boost filesystem, например.
Спасибо. Интересно. Сам недавно смотрел на POCO, но так и не решил использовать. Было бы очень интересно почитать
и особенно о
о модулях XML, ZIP, Data, Net
и особенно о
создании высокопроизводительных серверов на POCO
Картинка такая жизненная…
Sign up to leave a comment.
Portable Components, вспомогательные средства разработки ПО