Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
string_util.hpp
Go to the documentation of this file.
1// string_util.hpp
2//
3// This header provides several string utility functions and type traits to aid in
4// modern C++ string manipulation and conversion without relying on Boost.
5//
6// It includes:
7// - Operator+ overloads for concatenating std::string and std::string_view,
8// enabled only if the standard library lacks this support (__cpp_lib_string_view < 202403L).
9// - A case-insensitive string comparison function, iequals, for std::string_view.
10// - A trait (has_stream_extractor) to detect if a type T supports stream extraction (operator>>).
11// - A helper constant (dependent_false_v) for use in SFINAE and static_asserts in templates.
12// - A generic from_string template function that converts a std::string_view to a value of type T.
13// - For arithmetic types, it uses std::from_chars.
14// - For types constructible from std::string, it uses that constructor.
15// - Otherwise, if T supports operator>>, it falls back to istringstream extraction.
16// - If none of these apply, a static_assert is triggered.
17
18#pragma once
19
20#include <algorithm>
21#include <cctype>
22#include <charconv>
23#include <istream>
24#include <sstream>
25#include <stdexcept>
26#include <string>
27#include <string_view>
28#include <system_error>
29#include <type_traits>
30#include <utility>
31
32// Only define these overloads if the standard library doesn't provide them.
33#if !defined(__cpp_lib_string_view) || (__cpp_lib_string_view < 202403L)
34
36{
37
38// Overload for std::string + std::string_view.
39inline std::string operator+(const std::string& lhs, std::string_view rhs) { return lhs + std::string(rhs); }
40
41// Overload for std::string_view + std::string.
42inline std::string operator+(std::string_view lhs, const std::string& rhs) { return std::string(lhs) + rhs; }
43
44} // namespace hack_string_view
45
46// Bring the overloads into the global namespace
47using hack_string_view::operator+;
48
49#endif
50
51// A simple case-insensitive comparison using std::string_view.
52inline bool iequals(std::string_view a, std::string_view b)
53{
54 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](unsigned char ca, unsigned char cb) {
55 return std::tolower(ca) == std::tolower(cb);
56 });
57}
58
59// Trait to check if operator>> is defined for T from an std::istream.
60template <typename T, typename = void> struct has_stream_extractor : std::false_type
61{};
62
64template <typename T>
65struct has_stream_extractor<T, std::void_t<decltype(std::declval<std::istream&>() >> std::declval<T&>())>>
66 : std::true_type
67{};
69
70template <typename T> inline constexpr bool has_stream_extractor_v = has_stream_extractor<T>::value;
71
72// A helper for static_assert in an uninstantiated branch.
73template <typename> inline constexpr bool dependent_false_v = false;
74
75// from_string: converts a std::string_view to a value of type T.
76// 1. If T is arithmetic, use std::from_chars.
77// 2. Else if T is constructible from std::string, use that constructor.
78// 3. Else if T supports operator>> extraction, use an istringstream.
79// 4. Otherwise, trigger a static_assert.
80template <typename T> T from_string(std::string_view s)
81{
82 if constexpr (std::is_arithmetic_v<T>)
83 {
84 T result{};
85 auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), result);
86 if (ec != std::errc()) throw std::runtime_error("from_string: conversion failed for arithmetic type");
87 return result;
88 }
89 else if constexpr (std::is_constructible_v<T, std::string>)
90 {
91 return T{std::string(s)};
92 }
93 else if constexpr (has_stream_extractor_v<T>)
94 {
95 std::istringstream iss{std::string(s)};
96 T result{};
97 if (!(iss >> result))
98 throw std::runtime_error("from_string: conversion failed for non-arithmetic type using stream extraction");
99 return result;
100 }
101 else
102 {
103 static_assert(dependent_false_v<T>, "from_string: No conversion available for type T");
104 }
105}
Definition string_util.hpp:36
Definition qnum.hpp:403
bool iequals(std::string_view a, std::string_view b)
Definition string_util.hpp:52
constexpr bool has_stream_extractor_v
Definition string_util.hpp:70
constexpr bool dependent_false_v
Definition string_util.hpp:73
T from_string(std::string_view s)
Definition string_util.hpp:80
Definition string_util.hpp:61