Guitar
str.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <QString>
4 #include <QDebug>
5 #include <string>
6 #include <string_view>
7 #include <variant>
8 #include <vector>
9 
10 namespace misc {
11 
12 class str {
13 private:
14  std::variant<std::string_view, QString> str_;
15 public:
16  explicit str(char const *s) : str_(std::string_view(s)) {}
17  explicit str(char const *s, size_t n) : str_(std::string_view(s, n)) {}
18  explicit str(char const *begin, char const *end) : str_(std::string_view(begin, end - begin)) {}
19  explicit str(std::string_view sv) : str_(sv) {}
20  explicit str(std::vector<char> const &v) : str_(std::string_view(v.data(), v.size())) {}
21  explicit str(QString const &s) : str_(s) {}
22  explicit str(char16_t const *begin, char16_t const *end) : str_(QString::fromUtf16(begin, end - begin)) {}
23  explicit str(QByteArray const &ba) : str_(std::string_view(ba.data(), ba.size())) {}
24  bool empty() const
25  {
26  return std::visit([](auto &&arg) -> bool {
27  using T = std::decay_t<decltype(arg)>;
28  if constexpr (std::is_same_v<T, std::string_view>) {
29  return arg.empty();
30  } else if constexpr (std::is_same_v<T, QString>) {
31  return arg.isEmpty();
32  }
33  return true;
34  }, str_);
35  }
36  bool isEmpty() const
37  {
38  return empty();
39  }
40  explicit operator bool () const
41  {
42  return !empty();
43  }
44  std::string std_string() const
45  {
46  return std::visit([](auto &&arg) -> std::string {
47  using T = std::decay_t<decltype(arg)>;
48  if constexpr (std::is_same_v<T, std::string_view>) {
49  return std::string(arg);
50  } else if constexpr (std::is_same_v<T, QString>) {
51  return arg.toStdString();
52  }
53  return {};
54  }, str_);
55  }
56 
57  std::string_view std_string_view() const
58  {
59  return std::visit([](auto &&arg) -> std::string_view {
60  using T = std::decay_t<decltype(arg)>;
61  if constexpr (std::is_same_v<T, std::string_view>) {
62  return arg;
63  } else if constexpr (std::is_same_v<T, QString>) {
64 #if 0
65  std::string s = arg.toStdString();
66  return std::string_view(s);
67 #endif
68  // Q. 上のコードの s の寿命は?
69  // A. ここでは問題ない。なぜなら、QString::toStdString() は QString の内容をコピーして新しい std::string を作成するため、s はこの関数内で有効であり、返された std::string_view は s の内容を指すことになるから。ただし、この std::string_view を呼び出し元で使用する場合は、s がスコープ外になるため、呼び出し元で s を保持する必要がある。
70  // Q. この関数から抜けた時点で、s は破棄されるのでは?
71  // A. その通りです。上のコードでは、s はこのラムダ関数内で定義されているため、ラムダ関数が終了すると s は破棄されます。そのため、返された std::string_view は s の内容を指すことになりますが、s が破棄された後は、その std::string_view は不定の動作を引き起こす可能性があります。したがって、このコードは安全ではありません。
72  qDebug() << "Warning: Converting QString to std::string_view may lead to dangling reference. Consider using std::string instead.";
73  Q_ASSERT(0);
74  }
75  return {};
76  }, str_);
77  }
78 
79  std::vector<char> std_vector_char() const
80  {
81  return std::visit([](auto &&arg) -> std::vector<char> {
82  using T = std::decay_t<decltype(arg)>;
83  if constexpr (std::is_same_v<T, std::string_view>) {
84  return std::vector<char>(arg.begin(), arg.end());
85  } else if constexpr (std::is_same_v<T, QString>) {
86  std::string s = arg.toStdString();
87  return std::vector<char>(s.begin(), s.end());
88  }
89  return {};
90  }, str_);
91  }
92  QString qstring() const
93  {
94  return std::visit([](auto &&arg) -> QString {
95  using T = std::decay_t<decltype(arg)>;
96  if constexpr (std::is_same_v<T, std::string_view>) {
97  return QString::fromStdString(std::string(arg));
98  } else if constexpr (std::is_same_v<T, QString>) {
99  return arg;
100  }
101  return {};
102  }, str_);
103  }
104  QByteArray qbytearray() const
105  {
106  return std::visit([](auto &&arg) -> QByteArray {
107  using T = std::decay_t<decltype(arg)>;
108  if constexpr (std::is_same_v<T, std::string_view>) {
109  return QByteArray(arg.data(), arg.size());
110  } else if constexpr (std::is_same_v<T, QString>) {
111  return arg.toUtf8();
112  }
113  return {};
114  }, str_);
115  }
116  operator std::string() const
117  {
118  return std_string();
119  }
120  operator std::string_view() const
121  {
122  return std_string_view();
123  }
124  operator std::vector<char>() const
125  {
126  return std_vector_char();
127  }
128  operator QString() const
129  {
130  return qstring();
131  }
135 #if 0
136  operator QByteArray() const
137  {
138  return qbytearray();
139  }
140 #endif
141 };
142 
143 class strlist {
144 private:
145  std::vector<std::string_view> vec_;
146 public:
147  strlist(std::vector<std::string_view> const &vec)
148  : vec_(vec)
149  {
150  }
151  strlist(std::vector<std::string> const &vec)
152  {
153  vec_.reserve(vec.size());
154  for (auto const &s : vec) {
155  vec_.emplace_back(s);
156  }
157  }
158  operator std::vector<std::string> () const
159  {
160  std::vector<std::string> out;
161  for (auto const &s : vec_) {
162  out.emplace_back(s);
163  }
164  return out;
165  }
166 };
167 
168 }
169 
Definition: str.h:12
str(std::vector< char > const &v)
Definition: str.h:20
std::string std_string() const
Definition: str.h:44
str(char const *s, size_t n)
Definition: str.h:17
std::string_view std_string_view() const
Definition: str.h:57
QByteArray qbytearray() const
Definition: str.h:104
str(char const *s)
Definition: str.h:16
bool empty() const
Definition: str.h:24
str(QString const &s)
Definition: str.h:21
str(char16_t const *begin, char16_t const *end)
Definition: str.h:22
str(char const *begin, char const *end)
Definition: str.h:18
std::vector< char > std_vector_char() const
Definition: str.h:79
str(QByteArray const &ba)
Definition: str.h:23
str(std::string_view sv)
Definition: str.h:19
bool isEmpty() const
Definition: str.h:36
std::variant< std::string_view, QString > str_
Definition: str.h:14
QString qstring() const
Definition: str.h:92
Definition: str.h:143
strlist(std::vector< std::string_view > const &vec)
Definition: str.h:147
std::vector< std::string_view > vec_
Definition: str.h:145
strlist(std::vector< std::string > const &vec)
Definition: str.h:151
Definition: misc.h:20
Definition: GitTypes.h:78