C ++ 11 implements a simple lexical_cast, and 11 implements lexical_cast.
There is a lexical_cast in boost that can be used for conversion between basic types in a unified manner, such as conversion between strings to numbers, numbers to strings, bool, and strings and numbers. Boost: lexical_cast is easy to use:
# Include <boost/lexical_cast.hpp> # include <iostream> # include <string> # define ERROR_LEXICAL_CAST 1 int main () {using boost: lexical_cast; int a = 0; double B = 0.0; std: string s = ""; int e = 0; try {// ----- string --> value a = lexical_cast <int> ("123 "); B = lexical_cast <double> ("123.12"); // ----- value --> string s = lexical_cast <std: string> ("123456.7 "); // ----- Exception Handling demo e = lexical_cast <int> ("abc");} catch (boost: bad_lexical_cast & e) {// bad lexical cast: source type value cocould not be interpreted as target std: cout <e. what () <std: endl; return ERROR_LEXICAL_CAST;} std: cout <a <std: endl; // output: 123 std :: cout <B <std: endl; // output: 123.12 std: cout <s <std: endl; // output: 123456.7 return 0 ;}View Code
The lexical_cast method is missing in c ++ 11, but c ++ 11 provides some basic type conversion methods, such as to_string, atoi, atof, etc, however, we cannot use a common method to convert the basic types. Therefore, I want to convert the basic types by using lexical_cast similar to boost, this is also a development plan for our c ++ community.
Since c ++ 11 has provided some convenient methods, what I want to do is to combine them and provide a unified lexical_cast method.
The implementation idea is also very simple. There are mainly the following types of conversions: 1. number to String Conversion; 2. string to number conversion; 3. convert bool and string; 4. convert a number to bool. The specific implementation code is as follows:
#include <type_traits>#include <string>#include <cstdlib>#include <algorithm>#include <stdexcept>#include <cctype>#include <cstring>using namespace std;namespace detail{ const char* strue = "true"; const char* sfalse = "false"; template <typename To, typename From> struct Converter { }; //to numeric template <typename From> struct Converter<int, From> { static int convert(const From& from) { return std::atoi(from); } }; template <typename From> struct Converter<long, From> { static long convert(const From& from) { return std::atol(from); } }; template <typename From> struct Converter<long long, From> { static long long convert(const From& from) { return std::atoll(from); } }; template <typename From> struct Converter<double, From> { static double convert(const From& from) { return std::atof(from); } }; template <typename From> struct Converter<float, From> { static float convert(const From& from) { return (float)std::atof(from); } }; //to bool template <typename From> struct Converter<bool, From> { static typename std::enable_if<std::is_integral<From>::value, bool>::type convert(From from) { return !!from; } }; bool checkbool(const char* from, const size_t len, const char* s) { for (size_t i = 0; i < len; i++) { if (from[i] != s[i]) { return false; } } return true; } static bool convert(const char* from) { const unsigned int len = strlen(from); if (len != 4 && len != 5) throw std::invalid_argument("argument is invalid"); bool r = true; if (len == 4) { r = checkbool(from, len, strue); if (r) return true; } else { r = checkbool(from, len, sfalse); if (r) return false; } throw std::invalid_argument("argument is invalid"); } template <> struct Converter<bool, string> { static bool convert(const string& from) { return detail::convert(from.c_str()); } }; template <> struct Converter<bool, const char*> { static bool convert(const char* from) { return detail::convert(from); } }; template <> struct Converter<bool, char*> { static bool convert(char* from) { return detail::convert(from); } }; template <unsigned N> struct Converter<bool, const char[N]> { static bool convert(const char(&from)[N]) { return detail::convert(from); } }; template <unsigned N> struct Converter<bool, char[N]> { static bool convert(const char(&from)[N]) { return detail::convert(from); } }; //to string template <typename From> struct Converter<string, From> { static string convert(const From& from) { return std::to_string(from); } };}template <typename To, typename From>typename std::enable_if<!std::is_same<To, From>::value, To>::type lexical_cast(const From& from){ return detail::Converter<To, From>::convert(from);}template <typename To, typename From>typename std::enable_if<std::is_same<To, From>::value, To>::type lexical_cast(const From& from){ return from;}
It took more than an hour before and after, and a basic type conversion class was completed. Test the code again:
void test(){ cout<<lexical_cast<int>(1)<<endl; cout << lexical_cast<int>("1") << endl; cout << lexical_cast<long>("1") << endl; cout << lexical_cast<string>(1) << endl; cout << lexical_cast<bool>(1) << endl; cout << lexical_cast<double>("1.2") << endl; cout << lexical_cast<float>("1.2") << endl; string s = "true"; cout << lexical_cast<bool>(s) << endl; char* p = "false"; cout << lexical_cast<bool>(p) << endl; const char* q = "false"; cout << lexical_cast<bool>(q) << endl; cout << lexical_cast<bool>("false") << endl; cout << lexical_cast<bool>("test") << endl;}int main(){ try { test(); } catch (const std::exception& e) { cout << e.what() << endl; } return 0;}
Test results: