5

Intro (from Eric Lippert Blog) :

Vexing exceptions are the result of unfortunate design decisions. Vexing exceptions are thrown in a completely non-exceptional circumstance, and therefore must be caught and handled all the time.

The classic example of a vexing exception is Int32.Parse, which throws if you give it a string that cannot be parsed as an integer. But the 99% use case for this method is transforming strings input by the user, which could be any old thing, and therefore it is in no way exceptional for the parse to fail. Worse, there is no way for the caller to determine ahead of time whether their argument is bad without implementing the entire method themselves, in which case they wouldn't need to be calling it in the first place.

Now the important part:

This unfortunate design decision was so vexing that of course the frameworks team implemented TryParse shortly thereafter which does the right thing.

From MSDN Int32.TryParse:

Return Value Type: System.Boolean true if s was converted successfully; otherwise, false.

So colleague recenly was working on some small bit of code that required checking if a string is a number so after thinking about it and realizing there is no good C++ solution(basically it is a for__each/find_if or boost:lexical_cast try catch) I thought how nice it would be to have is_convertible or something from boost?

Ofc i can wrap boost lexical_cast and return true at the end of try block and return false at the end of catch block but I prefer existing practice :) solutions.

NoSenseEtAl
  • 23,776
  • 22
  • 102
  • 222
  • As an aside, note that while Eric’s article is very compelling it’s not logically coherent: the exceptions he describes as necessary evils (“exogenous”) aren’t actually necessary – just consider IO: C++ IO streams manage very well to model these conditions without use of exceptions, which Eric describes as necessary. – Konrad Rudolph Nov 28 '12 at 17:08
  • sorry I never cared about iostreams (and dont understand the hate they get :D) Do you talk about the fact that they have good(), bad(),... functions? – NoSenseEtAl Nov 28 '12 at 17:16
  • Essentially, yes. By default, they signal failure state not via exceptions but via flags, even such states that would raise an “exogenous” exception in .NET. – Konrad Rudolph Nov 28 '12 at 18:47
  • idk to be honest I would prefer one uniform way of doing stuff in c++, but tbh I dont have enough exp with return codes/flags/exceptions so my opinion doesnt really matter. :) – NoSenseEtAl Nov 28 '12 at 20:04

3 Answers3

4

If you can use boost, then you could use boost::conversion::try_lexical_convert:

#include <boost/lexical_cast/try_lexical_convert.hpp>

std::string str("1.2");
double res;
if(boost::conversion::try_lexical_convert<double>(str, res)){
   //everything normal
}
else{
   //we got a problem
}
ead
  • 27,136
  • 4
  • 67
  • 108
3

> So colleague recenly was working on some small bit of code that required checking if a string is a number so after thinking about it and realizing there is no good C++ solution

In C++11 you have std::stol and/or std::stod, which may do what you need.

Update If you don't want to use exceptions, then strtol(str, &endp) will do the conversion.

You can check if str == endp after the call; if they're the same, then no conversion was possible (since endp will point to the beginning of the unconverted portion of the string)

Like this:

strtol(str, &endp);
if (endp==str) { /* no conversion occurred */ }
Marshall Clow
  • 13,643
  • 1
  • 24
  • 44
  • Hi like I said in Q I prefer not to ab/use try/catch : "Ofc i can wrap boost lexical_cast and return true at the end of try block and return false at the end of catch block but I prefer existing practice :) solutions. " docs for strol: Exceptions std::invalid_argument if no conversion could be performed std::out_of_range if the converted value would fall out of the range of the result type. – NoSenseEtAl Nov 28 '12 at 17:10
  • 1
    In that case, take a look at `std::strtol` – Marshall Clow Nov 28 '12 at 17:37
  • " If no valid conversion could be performed, a zero value is returned (0L)." , so isNumber = str=="0" || strtol(str);, but thet woont work for "00","000"... :( – NoSenseEtAl Nov 28 '12 at 18:05
  • You can check the end_ptr returned. If it's the same as the pointer you passed in, then no conversion occurred. – Marshall Clow Nov 28 '12 at 20:55
  • 1
    `strtol(str, &endp ); if (endp==str) {}` no conversion occurred. – Marshall Clow Nov 28 '12 at 22:03
  • hi, please update your answer with last comment so I can accept it. – NoSenseEtAl Nov 29 '12 at 09:55
-1

Not really, to be honest, as far as I am aware there is no try_lexical_cast but there is two things you can do.

Own is use streams and test that the extraction was successful, not that in most cases lexical_cast uses streams anyway internally:

 std::string str="56.7";
 std::istringstream ss(str);
 double d;
 if(ss >> d) {
     //passed
 }
 else //failed

Or of course as you mention you can wrap lexical_cast

111111
  • 14,528
  • 6
  • 38
  • 58