You could use either Boost Spirit Numerical Parsers or (ab)use Boost Lexicalcast.
Boost Spirit allows you fine grained control of the format accepted, see e.g.
Here is a quick demo, that also shows how you could detect several possible numeric input formats (progressively) and return the type that was matched. Of course that could be overkill, but it should demonstrate how to use Spirit further.
The demo also shows how to advance the input iterator so you can easily continue parsing where the numeric input ended.
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
enum numeric_types
{
fmt_none,
fmt_float,
fmt_double,
fmt_uint,
fmt_int,
// fmt_hex, etc.
};
template <typename It>
bool is_numeric(It& f, It l, numeric_types& detected)
{
return qi::phrase_parse(f,l,
qi::uint_ [ qi::_val = fmt_uint ]
| qi::int_ [ qi::_val = fmt_int ]
| qi::float_ [ qi::_val = fmt_float ]
| qi::double_ [ qi::_val = fmt_double ]
,qi::space, detected);
}
template <typename It>
bool is_numeric(It& f, It l)
{
numeric_types detected = fmt_none;
return is_numeric(f, l, detected);
}
int main()
{
const std::string input = "124, -25, 582";
std::string::const_iterator it = input.begin();
bool ok = is_numeric(it, input.end());
if (ok)
{
std::cout << "parse success\n";
if (it!=input.end())
std::cerr << "trailing unparsed: '" << std::string(it,input.end()) << "'\n";
}
else
std::cerr << "parse failed: '" << std::string(it,input.end()) << "'\n";
return ok? 0 : 255;
}
false, rather have a single function that tries all permitted formats. An exception is a perfectly reasonable way to indicate that a string doesn't match an expected format. It need never propagate outside the function that knows that it doesn't know the proper format, and is "taking risks" by trying a few different formats in turn.