Skip to content

Instantly share code, notes, and snippets.

@RadAd
Created July 19, 2021 06:02
Show Gist options
  • Save RadAd/32c8886bd7aa1347d29973d6d58891d5 to your computer and use it in GitHub Desktop.
Save RadAd/32c8886bd7aa1347d29973d6d58891d5 to your computer and use it in GitHub Desktop.
#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