Boost logo

Boost :

From: Björn Karlsson (bjorn.karlsson_at_[hidden])
Date: 2002-01-25 08:03:27


Sorry, I forgot to mention that since the types can be deduced, you don't
have to specify the type:

double d;
std::string s="3.1415";
bool b=boost::lexical_cast(s, &d);

Bjorn

-----Original Message-----
From: Björn Karlsson
Sent: den 25 januari 2002 12:18
To: 'Boost'
Subject: [boost] Proposal for lexical_cast/lexical_convert

The reasoning below is the background for the proposal of adding a
nothrowing relative to lexical_cast, called lexical_convert.
There are two main reasons why lexical_cast isn't always a perfect fit (as I
see it):
0) In code that doesn't otherwise use exceptions, the error handling can
become awkward/messy/inconsistent when using lexical_cast.
1) When a failed conversion is not considered an error, the exception
handling stands in the way of code clarity.
I seem to recall an earlier proposal for a lexical_cast, something like
"template<typename Target, typename Source> bool lexical_cast(Source arg,
Target* result)", but obviously, that doesn't look like a cast anymore.
It's still useful though, so why don't we give it another name?
I think lexical_convert states the meaning quite clearly:
template<typename Target, typename Source> bool lexical_convert(Source arg,
Target* result)
The implementation would be "borrowed" from lexical_cast:
   template<typename Target, typename Source>
   bool lexical_convert(Source arg, Target* result)
   {
# ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
      std::strstream interpreter; // for out-of-the-box g++ 2.95.2
# else
      std::stringstream interpreter;
# endif
      if(!result || !(interpreter << arg) || !(interpreter >> *result) ||
      !(interpreter >> std::ws).eof())
         return false;
      return true;
   }
Passing the target by pointer or reference is a tough call - the intention
is made clear by using a pointer, but that allows for code like: int* p;
boost::lexical_convert<int>(s, p);. On the other hand, passing by reference
solves the problem but makes the code less clear. I hesitate to claim that
one version is better than the other, so I'll leave it at that and a test
for !result (in the end, I think this one boils down to personal
preference).
There's not much code, so duplication probably doesn't matter, but the
throwing lexical_cast could obviously be implemented in terms of
lexical_convert:
template <typename Target, typename Source> Target lexical_cast(Source arg)
{
   Target result;
   if (!lexical_convert<Target>(arg, &result))
      throw bad_lexical_cast();
   return result;
}
Sample client code:
void lexical_cast_example(const std::string& s) {
   int i=0;
   if (boost::lexical_convert<int>(s, &i)) {
      std::cout << i << "\n";
   }
   else {
      std::cout << "bad lexical conversion: source type value could not be
interpreted as target";
   }
   try {
      i=boost::lexical_cast<int>(s);
      std::cout << i << "\n";
   }
   catch(boost::bad_lexical_cast& e) {
      std::cout << e.what();
   }
}
The point of the example (for the case where a failed conversion is not
considered an error) is that the else could simply be omitted, and that (in
this case) there's no reason to throw if noone wants to catch :-).
An open issue would be where the stuff should go - lexical_cast.hpp is very
specific, but maybe the right place anyway?

Bjorn

Info: http://www.boost.org Send unsubscribe requests to:
<mailto:boost-unsubscribe_at_[hidden]>

Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk