What you want exists in Boost Convert:
Boost.Convert builds on the boost::lexical_cast experience and takes
those type conversion/transformation-related ideas further
- to be applicable to a wider range of conversion-related deployment scenarios,
- to provide a more flexible, configurable and extendible type-conversion framework,
- to provide generic consistent behavior,
- to unify and to uniformly deploy various conversion facilities through one consistent interface.
Simple Usage
You can e.g. use stream conversion:
boost::cnv::cstream converter;
You can configure it with the manipulators you want, e.g.:
converter(std::hex)(std::skipws); // IO manipulators
You could use directly:
boost::optional<int> i;
converter(s, i);
std::cout << i << std::endl; // 1000
But I'd suggest applying with pre-configured error-handling:
auto f = apply<int>(std::ref(converter))
.value_or(-1); // decorate error-handling
Now you can simply write:
for (auto s : cases)
std::cout << f(s) << std::endl;
Live Demo
Live On Coliru
#include <boost/convert.hpp>
#include <boost/convert/stream.hpp>
#include <iostream>
static const std::string cases[]{
"0x3e8", "3e8", "-7a", "-0x7a",
"0x-7a", // error
};
int main() {
boost::cnv::cstream converter;
converter(std::hex)(std::skipws); // IO manipulators
auto f = apply<int>(std::ref(converter)).value_or(-1); // decorate error-handling
for (auto s : cases)
std::cout << std::quoted(s) << " -> " << f(s) << std::endl;
auto g = apply<int>(std::ref(converter)); // throwing
for (auto s : cases)
try {
std::cout << std::quoted(s) << " -> " << g(s) << std::endl;
} catch (std::exception const& e) {
std::cout << e.what() << std::endl;
}
}
Prints
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> -1
"0x3e8" -> 1000
"3e8" -> 1000
"-7a" -> -122
"-0x7a" -> -122
"0x-7a" -> Attempted to access the value of an uninitialized optional object.