Program Listing for File conversion.hpp¶
↰ Return to documentation for file (SeQuant/core/utility/conversion.hpp)
#ifndef SEQUANT_UTILITY_CONVERSION_HPP
#define SEQUANT_UTILITY_CONVERSION_HPP
#include <SeQuant/core/utility/exception.hpp>
#include <charconv>
#include <concepts>
#include <string_view>
#include <system_error>
#include <typeinfo>
namespace sequant {
class ConversionException : public Exception {
public:
using Exception::Exception;
};
namespace {
template <typename T, typename Arg>
requires(std::integral<T> || std::floating_point<T>)
T string_to_impl(std::string_view str, Arg &&arg) {
T val = 0;
std::from_chars_result result =
std::from_chars(str.begin(), str.end(), val, std::forward<Arg>(arg));
// Note: Beware that typeid(T).name() yields something implementation defined,
// which may or may not be useful for a human
if (result.ec != std::errc{}) {
switch (result.ec) {
case std::errc::invalid_argument:
throw ConversionException("'" + std::string(str) +
"' is not a valid '" + typeid(T).name() +
"'");
case std::errc::result_out_of_range:
throw ConversionException("'" + std::string(str) +
"' is out of range for type '" +
typeid(T).name() + "'");
default:
throw ConversionException("Unexpected conversion error");
}
}
if (result.ptr != str.end()) {
// Incomplete parse
throw ConversionException("'" + std::string(str) +
"' could not be fully parsed as a '" +
typeid(T).name() + "'");
}
return val;
}
} // namespace
template <typename T>
concept string_to_supports =
requires(const char *c, T &v) { std::from_chars(c, c + 1, v); };
template <std::integral T>
T string_to(std::string_view str, int base = 10) {
static_assert(string_to_supports<T>,
"Your C++ standard library is missing a std::from_chars "
"implementation for this integral type");
return string_to_impl<T>(str, base);
}
template <std::floating_point T>
T string_to(std::string_view str,
std::chars_format fmt = std::chars_format::general) {
static_assert(string_to_supports<T>,
"Your C++ standard library is missing a std::from_chars "
"implementation for this floating point type");
return string_to_impl<T>(str, fmt);
}
} // namespace sequant
#endif