Created
July 19, 2021 06:02
-
-
Save RadAd/32c8886bd7aa1347d29973d6d58891d5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <charconv> | |
#include <type_traits> | |
#include <cwctype> | |
// ----- | |
// Helper alias templates | |
template<typename T> | |
using EnableIfIntegral = std::enable_if_t<std::is_integral<T>::value, bool>; | |
template<typename T> | |
using EnableIfFloating = std::enable_if_t<std::is_floating_point<T>::value, bool>; | |
template<typename T> | |
using EnableIfChar = std::enable_if_t<std::is_same<char, T>::value, bool>; | |
template<typename T> | |
using EnableIfWChar = std::enable_if_t<std::is_same<wchar_t, T>::value, bool>; | |
inline char* copy_number_chars(char* buf, const wchar_t* begin, const wchar_t* end) | |
{ | |
while (begin != end) | |
{ | |
wchar_t wc = *begin; | |
if (std::iswspace(wc) || wc == L'+' || wc == L'-') | |
*buf++ = static_cast<char>(wc); | |
else | |
break; | |
++begin; | |
} | |
while (begin != end) | |
{ | |
wchar_t wc = *begin; | |
if (std::iswdigit(wc) || wc == L'.') | |
*buf++ = static_cast<char>(wc); | |
else | |
break; | |
++begin; | |
} | |
return buf; | |
} | |
// ----- | |
// from_chars function templates for C-style arrays | |
template<std::size_t N, typename T, EnableIfIntegral<T> = true> | |
std::from_chars_result from_chars(const char(&a)[N], T& value, int base = 10) { | |
return std::from_chars(a, a + N, value, base); | |
} | |
template<std::size_t N, typename T, EnableIfIntegral<T> = true> | |
std::from_chars_result from_chars(const wchar_t(&a)[N], T& value, int base = 10) { | |
char buf[20]; | |
const char* b = copy_number_chars(buf, a, a + N); | |
return std::from_chars(buf, b, value, base); | |
// TODO convert std::from_chars_result to std::from_wchars_result | |
} | |
template<std::size_t N, typename T, EnableIfFloating<T> = true> | |
std::from_chars_result from_chars(const char(&a)[N], T& value, std::chars_format fmt = std::chars_format::general) { | |
return std::from_chars(a, a + N, value, fmt); | |
} | |
template<std::size_t N, typename T, EnableIfFloating<T> = true> | |
std::from_chars_result from_chars(const wchar_t(&a)[N], T& value, std::chars_format fmt = std::chars_format::general) { | |
char buf[20]; | |
const char* b = copy_number_chars(buf, a, a + N); | |
return std::from_chars(buf, b, value, fmt); | |
// TODO convert std::from_chars_result to std::from_wchars_result | |
} | |
// ----- | |
// from_chars function templates for random access containers | |
template<typename Cont, typename T, EnableIfIntegral<T> = true, EnableIfChar<typename Cont::value_type> = true> | |
std::from_chars_result from_chars(const Cont& c, T& value, int base = 10) { | |
return std::from_chars(c.data(), c.data() + c.size(), value, base); | |
} | |
template<typename Cont, typename T, EnableIfIntegral<T> = true, EnableIfWChar<typename Cont::value_type> = true> | |
std::from_chars_result from_chars(const Cont& c, T& value, int base = 10) { | |
char buf[20]; | |
const char* b = copy_number_chars(buf, c.data(), c.data() + c.size()); | |
return std::from_chars(buf, b, value, base); | |
// TODO convert std::from_chars_result to std::from_wchars_result | |
} | |
template<typename Cont, typename T, EnableIfFloating<T> = true, EnableIfChar<typename Cont::value_type> = true> | |
std::from_chars_result from_chars(const Cont& c, T& value, std::chars_format fmt = std::chars_format::general) { | |
return std::from_chars(c.data(), c.data() + c.size(), value, fmt); | |
} | |
template<typename Cont, typename T, EnableIfFloating<T> = true, EnableIfWChar<typename Cont::value_type> = true> | |
std::from_chars_result from_chars(const Cont& c, T& value, std::chars_format fmt = std::chars_format::general) { | |
char buf[20]; | |
const char* b = copy_number_chars(buf, c.data(), c.data() + c.size()); | |
return std::from_chars(buf, b, value, fmt); | |
// TODO convert std::from_chars_result to std::from_wchars_result | |
} | |
// ----- | |
// to_chars function templates for C-style arrays | |
template<std::size_t N, typename T, EnableIfIntegral<T> = true> | |
std::to_chars_result to_chars(char(&a)[N], T value, int base = 10) { | |
std::to_chars_result res = std::to_chars(a, a + (N - 1), value, base); | |
*res.ptr = '\0'; | |
return res; | |
} | |
template<std::size_t N, typename T, EnableIfFloating<T> = true> | |
std::to_chars_result to_chars(char(&a)[N], T value, std::chars_format fmt) { | |
std::to_chars_result res = std::to_chars(a, a + (N - 1), value, fmt); | |
*res.ptr = '\0'; | |
return res; | |
} | |
template<std::size_t N, typename T, EnableIfFloating<T> = true> | |
std::to_chars_result to_chars(char(&a)[N], T value, std::chars_format fmt, int precision) { | |
std::to_chars_result res = std::to_chars(a, a + (N - 1), value, fmt, precision); | |
*res.ptr = '\0'; | |
return res; | |
} | |
// ----- | |
// to_chars function templates for random access containers | |
template<typename Cont, typename T, EnableIfIntegral<T> = true, EnableIfChar<typename Cont::value_type> = true> | |
std::to_chars_result to_chars(Cont& c, T value, int base = 10) { | |
std::to_chars_result res = std::to_chars(c.data(), c.data() + (c.size() - 1), value, base); | |
*res.ptr = '\0'; | |
return res; | |
} | |
template<typename Cont, typename T, EnableIfFloating<T> = true, EnableIfChar<typename Cont::value_type> = true> | |
std::to_chars_result to_chars(Cont& c, T value, std::chars_format fmt) { | |
std::to_chars_result res = std::to_chars(c.data(), c.data() + (c.size() - 1), value, fmt); | |
*res.ptr = '\0'; | |
return res; | |
} | |
template<typename Cont, typename T, EnableIfFloating<T> = true, EnableIfChar<typename Cont::value_type> = true> | |
std::to_chars_result to_chars(Cont& c, T value, std::chars_format fmt, int precision) { | |
std::to_chars_result res = std::to_chars(c.data(), c.data() + (c.size() - 1), value, fmt, precision); | |
*res.ptr = '\0'; | |
return res; | |
} | |
#include <string> | |
#include <iostream> | |
int main() { | |
const char str[] = "3.1416"; | |
float pi; | |
double morePi; | |
auto r1 = ::from_chars(str, pi); | |
auto r2 = ::from_chars(str, morePi); | |
std::cout << "pi " << pi << "\n"; | |
std::cout << "morePi " << morePi << "\n"; | |
std::string s("3.1416"); | |
auto r3 = ::from_chars(s, pi); | |
auto r4 = ::from_chars(s, morePi); | |
std::cout << "pi " << pi << "\n"; | |
std::cout << "morePi " << morePi << "\n"; | |
std::wstring sw(L"3.1416"); | |
auto r5 = ::from_chars(sw, pi); | |
auto r6 = ::from_chars(sw, morePi); | |
std::cout << "pi " << pi << "\n"; | |
std::cout << "morePi " << morePi << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment