Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: RedApe Беларусь  
Дата: 23.09.15 12:19
Оценка:
А вот интересно, не существует способа при помощи lexical_cast преобразовать строку в число не зная заранее является ли строка корректным числом без выброса исключения?

  std::string text = GetValueFromEdit();
  double d;
  try 
  {
    d = boost::lexical_cast<double>(text);
  } catch(boost::bad_lexical_case&) 
  {
    d = 0;
  }

  // почему нет такого варианта
  if (!boost::lexical_cast<double>(text, d)) 
  {
     d = 0;
  }

  // или какого-нибудь еще


Есть же, к примеру, две версии dynamic_cast, с исключениями и без исключений.
Как же тот принцип что исключения нужны для исключительных ситуаций?

Или все пользуются каким-то другим методом?
--
RedApe
Re: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: Vamp Россия  
Дата: 23.09.15 12:39
Оценка:
RA>Или все пользуются каким-то другим методом?

std::stod
Да здравствует мыло душистое и веревка пушистая.
Re: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: Igore Россия  
Дата: 23.09.15 12:51
Оценка:
Здравствуйте, RedApe, Вы писали:

RA>А вот интересно, не существует способа при помощи lexical_cast преобразовать строку в число не зная заранее является ли строка корректным числом без выброса исключения?

Нет
RA>Или все пользуются каким-то другим методом?
Обертка
template< typename T, typename U >
boost::optional< T > LexicalCastNoThrow( const U& val )
{
     boost::optional< T > ret;
     try
     {
          ret = boost::lexical_cast< T >( val );
     }
     catch( std::exception& )
     {
///...
     }
     return ret;
}
// ну или посмотреть внутрь и использовать try_lexical_convert
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
    Target result;

    if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
        boost::conversion::detail::throw_bad_cast<Source, Target>();
    }

    return result;
}

ИМХО некоторые места буста пишут не для людей, а для себя, таже проблема в boost::format, ошибся в параметрах лови исключение, нет чтобы продолжить работу и вывести в лог что передано не верное количество аргументов
Re[2]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: B0FEE664  
Дата: 23.09.15 13:02
Оценка:
Здравствуйте, Vamp, Вы писали:

RA>>Или все пользуются каким-то другим методом?

V>std::stod
Да, но:

Exceptions
If no conversion could be performed, an invalid_argument exception is thrown.
If the value read is out of the range of representable values by a double (in some library implementations, this includes underflows), an out_of_range exception is thrown.

так что std::strtod.
И каждый день — без права на ошибку...
Re: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: PM  
Дата: 23.09.15 17:47
Оценка: 6 (2) +1 -1
Здравствуйте, RedApe, Вы писали:

RA>А вот интересно, не существует способа при помощи lexical_cast преобразовать строку в число не зная заранее является ли строка корректным числом без выброса исключения?


RA>
RA>  std::string text = GetValueFromEdit();
RA>  double d;
RA>  try 
RA>  {
RA>    d = boost::lexical_cast<double>(text);
RA>  } catch(boost::bad_lexical_case&) 
RA>  {
RA>    d = 0;
RA>  }

RA>  // почему нет такого варианта
RA>  if (!boost::lexical_cast<double>(text, d)) 
RA>  {
RA>     d = 0;
RA>  }

RA>  // или какого-нибудь еще
  
RA>


Такой вариант имеет тот же фатальный недостаток, что и все функции с возвратом кода ошибки — его легко проигнорировать. И невозможно инициализировать константу.
Можно, конечно, сделать перегрузку с дополнительным параметром для кода ошибки, но его тоже легко игнорировать:

template<typename Source, typename Target>
Target lexical_cast<Source const& src, boost::system::error_code& error);

boost::system::error_code err;
double const d = lexical_cast<double>(text, err);
if (err)
{
    // handle conversion error
}



RA>Есть же, к примеру, две версии dynamic_cast, с исключениями и без исключений.

RA>Как же тот принцип что исключения нужны для исключительных ситуаций?

RA>Или все пользуются каким-то другим методом?


Если у вас ошибка конверсии это неисключительная ситуация, используйте предназначенные для этого функции, например strtod

В Boost 1.59 появилась библиотека Convert в которой предусмотрены разные случаи обработки ошибок — бросание исключения, возврат значения по умолчанию, возврат boost::optional
Re[2]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: zaufi Земля  
Дата: 29.09.15 10:29
Оценка: +1 -2
Здравствуйте, Igore, Вы писали:

I>ИМХО некоторые места буста пишут не для людей, а для себя, таже проблема в boost::format, ошибся в параметрах лови исключение, нет чтобы продолжить работу и вывести в лог что передано не верное количество аргументов


в какой такой log??? откуда какой-то там format должен занть что у тебя лог и как с ним работать?
не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)
Re[3]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: RedApe Беларусь  
Дата: 29.09.15 10:39
Оценка: +1 -1
Здравствуйте, zaufi, Вы писали:

Z>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)


А как от пользователя получать данные?

Даже при уровне программы Hello World, запросить у пользователя число и то уже проблема. Нужно либо использовать отлов исключений либо С функции либо в 2015 году писать свою реализацию функции для подобных вещей. Все таки C++ иногда сильно раздражает
--
RedApe
Re[4]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: zaufi Земля  
Дата: 29.09.15 13:30
Оценка:
Здравствуйте, RedApe, Вы писали:

RA>Здравствуйте, zaufi, Вы писали:


Z>>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)


RA>А как от пользователя получать данные?


RA>Даже при уровне программы Hello World, запросить у пользователя число и то уже проблема. Нужно либо использовать отлов исключений либо С функции либо в 2015 году писать свою реализацию функции для подобных вещей. Все таки C++ иногда сильно раздражает


да, нужно испольовать try/catch! и какая с этим проблема?
Re[5]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: T4r4sB Россия  
Дата: 29.09.15 13:37
Оценка: -1
Здравствуйте, zaufi, Вы писали:

Z>да, нужно испольовать try/catch! и какая с этим проблема?


-fno-exceptions
Re[3]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: Igore Россия  
Дата: 29.09.15 14:41
Оценка:
Здравствуйте, zaufi, Вы писали:

I>>ИМХО некоторые места буста пишут не для людей, а для себя, таже проблема в boost::format, ошибся в параметрах лови исключение, нет чтобы продолжить работу и вывести в лог что передано не верное количество аргументов

Z>в какой такой log???
В любой, мне как пользователю все равно, мне главное чтобы исключения не было.
Z>откуда какой-то там format должен занть что у тебя лог и как с ним работать?
А он и не должен знать, он должен работать а не исключения кидать.
Z>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)
Клёво, только давай без сферо коней, не хочешь ошибок не программируй. Все допускают ошибки, и пока мой опыт говорит что лучше продолжить работу и вывести ошибку куда-либо std::cerr или неважно куда, чем кинуть исключение обосновав что это правильно с эстетической точки зрения. Я пока видел 2 вида использования boost::format, первый мы формируем текст который идет куда-либо и если там ошибка то мы не сможем продолжить работу, в этом случае кидай исключение или нет, неважно, ты это сразу поймаешь. Второй это вывод этой строки для отладки, интефейса или еще чего, где если ошибка есть, то нам это особо не важно, главное чтобы мы продолжили работать, так как если из какого-нибудь левого else вылетит исключение при редко возникающих обстоятельствах, это обычно очень плохо, так как код не пишут на поддержку таких редких случаев(там просто не должно быть исключений).
Re[5]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: Igore Россия  
Дата: 29.09.15 14:59
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>>>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)

RA>>А как от пользователя получать данные?
RA>>Даже при уровне программы Hello World, запросить у пользователя число и то уже проблема. Нужно либо использовать отлов исключений либо С функции либо в 2015 году писать свою реализацию функции для подобных вещей. Все таки C++ иногда сильно раздражает

Z>да, нужно испольовать try/catch! и какая с этим проблема?

Кроме многословности никакая. Я вот считаю что ввод не числа это нормальная ситуация, а не исключительная, все ошибаются
Re[5]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: RedApe Беларусь  
Дата: 29.09.15 17:47
Оценка: +1
Здравствуйте, zaufi, Вы писали:

Z>да, нужно испольовать try/catch! и какая с этим проблема?


Он уродлив. И в данном месте он "естетически" не подходит.
Все равно как если бы std::shared_ptr не содержал бы оператора проверки на отсутствие и всегда приходилось бы вместо
std::shared_ptr<A> a = get_pointer_that_can_be_null();
if (a)
{
  a->use_value();
}


Писать так
std::shared_ptr<A> a = get_pointer_that_can_be_null();
try
{
  a->use_value();
} catch(std::bad_shared_ptr&)
{ // do nothing
}


Согласись, что второй вариант уродлив. Зачем мне пытаться использовать возможно-некорректное-значение и сразу же на месте ловить исключение и игнорировать его?

В lexical_cast блок try/catch навязывается как плохая замена if/else.
--
RedApe
Re: Потому что "C++ style"
От: Basil2 Россия https://starostin.msk.ru
Дата: 04.12.15 07:10
Оценка: -2
Здравствуйте, RedApe, Вы писали:

RA>Есть же, к примеру, две версии dynamic_cast, с исключениями и без исключений.

Касты (с натяжкой) можно назвать наследием С, потэтому и две версии, имхо.

RA>Или все пользуются каким-то другим методом?

Если ты не хочешь исключений, то да придется сделать обертку. Библиотека предоставляет тебе стандартный для языка способ информирования об ошибках, хочешь своего — крутись
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[2]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: DarkEld3r  
Дата: 07.12.15 13:21
Оценка:
Здравствуйте, Igore, Вы писали:

I>ИМХО некоторые места буста пишут не для людей, а для себя, таже проблема в boost::format, ошибся в параметрах лови исключение, нет чтобы продолжить работу и вывести в лог что передано не верное количество аргументов

Поведение boost::format можно настроить и игнорировать ошибки.
Re[5]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: sts  
Дата: 22.12.15 20:08
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, RedApe, Вы писали:


RA>>Здравствуйте, zaufi, Вы писали:


Z>>>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)


RA>>А как от пользователя получать данные?


RA>>Даже при уровне программы Hello World, запросить у пользователя число и то уже проблема. Нужно либо использовать отлов исключений либо С функции либо в 2015 году писать свою реализацию функции для подобных вещей. Все таки C++ иногда сильно раздражает


Z>да, нужно испольовать try/catch! и какая с этим проблема?


Производительность, особенно на x64.
Ну и вообще не аккуратненько, ведь исключение — это ошибка, а здесь это не ошибка.
Re[2]: Потому что "C++ style"
От: sts  
Дата: 22.12.15 20:14
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Здравствуйте, RedApe, Вы писали:


RA>>Есть же, к примеру, две версии dynamic_cast, с исключениями и без исключений.

B>Касты (с натяжкой) можно назвать наследием С, потэтому и две версии, имхо.

RA>>Или все пользуются каким-то другим методом?

B>Если ты не хочешь исключений, то да придется сделать обертку. Библиотека предоставляет тебе стандартный для языка способ информирования об ошибках, хочешь своего — крутись

Нет возможности не платить за то, что не нужно.
И оно идет в разрез с принципами этого нашего языка.
Re[3]: Потому что "C++ style"
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.12.15 09:52
Оценка:
Здравствуйте, sts, Вы писали:

RA>>>Или все пользуются каким-то другим методом?

B>>Если ты не хочешь исключений, то да придется сделать обертку. Библиотека предоставляет тебе стандартный для языка способ информирования об ошибках, хочешь своего — крутись

sts>Нет возможности не платить за то, что не нужно.

sts>И оно идет в разрез с принципами этого нашего языка.

Это было в С. В С++ принцип в целом сохранился, но исключения — это исключение из данного правила, уж простите за каламбур
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[4]: Потому что "C++ style"
От: sts  
Дата: 23.12.15 11:09
Оценка:
Здравствуйте, Basil2, Вы писали:

B>>>Если ты не хочешь исключений, то да придется сделать обертку. Библиотека предоставляет тебе стандартный для языка способ информирования об ошибках, хочешь своего — крутись


sts>>Нет возможности не платить за то, что не нужно.

sts>>И оно идет в разрез с принципами этого нашего языка.

B>Это было в С. В С++ принцип в целом сохранился, но исключения — это исключение из данного правила, уж простите за каламбур


Генерирование исключения слишком дорого, чтобы кидаться ими направо и налево.
Re[5]: Потому что "C++ style"
От: Basil2 Россия https://starostin.msk.ru
Дата: 23.12.15 11:20
Оценка: +1
Здравствуйте, sts, Вы писали:

sts>>>Нет возможности не платить за то, что не нужно.

sts>>>И оно идет в разрез с принципами этого нашего языка.

B>>Это было в С. В С++ принцип в целом сохранился, но исключения — это исключение из данного правила, уж простите за каламбур


sts>Генерирование исключения слишком дорого, чтобы кидаться ими направо и налево.

Да, и что с того? Тем не менее этот механизм был добавлен в С++, и даже взят за в стандартной библиотеке. Кидаться же направо и налево никто не предлгает
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[6]: Почему boost::lexical_cast при неудаче всегда выбрасывает ис
От: zaufi Земля  
Дата: 29.12.15 08:38
Оценка:
Здравствуйте, sts, Вы писали:

sts>Здравствуйте, zaufi, Вы писали:


Z>>Здравствуйте, RedApe, Вы писали:


RA>>>Здравствуйте, zaufi, Вы писали:


Z>>>>не хочешь исключений -- не допускай ошибок! (например сделай адекватные юнит и coverage тесты)


RA>>>А как от пользователя получать данные?


RA>>>Даже при уровне программы Hello World, запросить у пользователя число и то уже проблема. Нужно либо использовать отлов исключений либо С функции либо в 2015 году писать свою реализацию функции для подобных вещей. Все таки C++ иногда сильно раздражает


Z>>да, нужно испольовать try/catch! и какая с этим проблема?


sts>Производительность, особенно на x64.


пожайлуста не смешите мои тапки... %) там где нужна производительность boost::lexical_cast и близко нету... ниша boost::lexical_cast это скорее удобство в разработке, но никак не производительность!

sts>Ну и вообще не аккуратненько, ведь исключение — это ошибка, а здесь это не ошибка.


отчегоже? lexical_cast понятия не имеет ошибка это или нет в твоем приложении... для него невозможность получить результат это очень даже ошибка, о чем он и сообщает исключением. чтобы сделать это неошибкой нужно поставить try/catch и правильно отреагировать на неправильный пользовательский ввод... -- это просто разные уровни... и как водится, когда нижний уровень не знает (да и не может знать) что делать с той или иной ошибкой, он уведомляет более верхний уровень исключением, предотвращая таким образом попытки (сознательные или возникшие по недосмотру) воспользоваться неверным результатом, что в свою очередь делает твой код более безопастным.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.