Console Library 4.7.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
box.h
Go to the documentation of this file.
1
8
9/*
10Copyright (c) 2026 MrXie1109
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#pragma once
32#include <vector>
33#include <typeinfo>
34#include <utility>
35#include <ostream>
36#include <memory>
37#include <cstdlib>
38#include "strpp.h"
39#include "csexc.h"
40#include "literals.h"
41
42namespace console
43{
50 class Item
51 {
52 private:
54 struct Base
55 {
56 virtual ~Base() {}
57 virtual Base *clone() const = 0;
58 virtual void print(std::ostream &) const = 0;
59 virtual std::string str() const = 0;
60 virtual const std::type_info &type() const = 0;
61 };
62
67 template <typename T>
68 struct Derived : Base
69 {
70 T value;
71
76 Derived(const T &v) : value(v) {}
77
82 Derived(T &&v) : value(std::move(v)) {}
83
88 Base *clone() const override
89 {
90 return new Derived(value);
91 }
92
97 void print(std::ostream &os) const override
98 {
99 repr(value, os);
100 }
101
106 std::string str() const override
107 {
108 std::ostringstream oss;
109 repr(value, oss);
110 return oss.str();
111 }
112
117 const std::type_info &type() const override
118 {
119 return typeid(T);
120 }
121 };
122
123 Base *ptr;
124
125 public:
127 Item() : ptr(nullptr) {}
128
134 template <typename T>
135 Item(T &&value)
136 : ptr(new Derived<typename std::decay<T>::type>(
137 std::forward<T>(value))) {}
138
143 Item(const Item &other)
144 : ptr(other.ptr ? other.ptr->clone() : nullptr) {}
145
150 Item(Item &&other) noexcept : ptr(other.ptr)
151 {
152 other.ptr = nullptr;
153 }
154
161 template <typename T>
163 {
164 if (ptr == nullptr)
165 throw bad_get("empty item");
166 if (typeid(T) != ptr->type())
167 throw bad_get(std::string("type mismatch: ") +
168 tiname(typeid(T)) +
169 " and " +
170 tiname(ptr->type()));
171 return ((Derived<T> *)ptr)->value;
172 }
173
180 template <typename T>
182 {
183 return ((Derived<T> *)ptr)->value;
184 }
185
192 template <typename T>
193 const T &get() const
194 {
195 if (ptr == nullptr)
196 throw bad_get("empty item");
197 if (typeid(T) != ptr->type())
198 throw bad_get(std::string("type mismatch: ") +
199 typeid(T).name() +
200 " and " +
201 ptr->type().name());
202 return ((Derived<T> *)ptr)->value;
203 }
204
211 template <typename T>
212 const T &unsafe_get() const
213 {
214 return ((Derived<T> *)ptr)->value;
215 }
216
222 const Item &operator=(const Item &other)
223 {
224 if (this != &other)
225 {
226 Base *new_ptr = other.ptr ? other.ptr->clone() : nullptr;
227 delete ptr;
228 ptr = new_ptr;
229 }
230 return *this;
231 }
232
238 const Item &operator=(Item &&other) noexcept
239 {
240 if (this != &other)
241 {
242 delete ptr;
243 ptr = other.ptr;
244 other.ptr = nullptr;
245 }
246 return *this;
247 }
248
255 friend std::ostream &operator<<(std::ostream &os, const Item &item)
256 {
257 item.ptr->print(os);
258 return os;
259 }
260
265 std::string str() const
266 {
267 return ptr->str();
268 }
269
271 ~Item() { delete ptr; }
272 };
273
280 class Box : public std::vector<Item>
281 {
282 public:
288 template <class... Args>
289 Box(Args &&...args)
290 : std::vector<Item>({Item(std::forward<Args>(args))...}) {}
291
299 template <class T>
300 T &get(size_t index)
301 {
302 return std::vector<Item>::at(index).get<T>();
303 }
304
312 template <typename T>
313 T &unsafe_get(size_t index)
314 {
315 return std::vector<Item>::operator[](index).unsafe_get<T>();
316 }
317
324 template <class... Args>
325 void unpack(Args &...args)
326 {
327 size_t i = 0;
328 int _[] = {0, ((args = get<Args>(i++)), 0)...};
329 (void)_;
330 }
331
338 template <class... Args>
339 void unsafe_unpack(Args &...args)
340 {
341 size_t i = 0;
342 int _[] = {0, ((args = unsafe_get<Args>(i++)), 0)...};
343 (void)_;
344 }
345
352 friend std::ostream &operator<<(std::ostream &os, const Box &box)
353 {
354 if (box.empty())
355 return os << "()";
356 auto it = box.begin();
357 os << '(' << *it;
358 while (++it != box.end())
359 os << ", " << *it;
360 return os << ')';
361 }
362 };
363}
void unpack(Args &...args)
将 Box 中的元素按顺序解包到多个变量中(类型安全)。
Definition box.h:325
T & get(size_t index)
类型安全地获取指定索引处的元素(非常量版本)。
Definition box.h:300
Box(Args &&...args)
从任意数量、任意类型的值构造 Box。
Definition box.h:289
friend std::ostream & operator<<(std::ostream &os, const Box &box)
将 Box 输出到流,格式类似于元组 (elem1, elem2, ...)。
Definition box.h:352
T & unsafe_get(size_t index)
不安全地获取指定索引处的元素(非常量版本)。
Definition box.h:313
void unsafe_unpack(Args &...args)
将 Box 中的元素按顺序解包到多个变量中(不安全版本)。
Definition box.h:339
可存储任意类型单个对象的类型擦除包装器。
Definition box.h:51
T & unsafe_get()
不安全地获取存储值的引用(非常量版本)。
Definition box.h:181
Item(Item &&other) noexcept
移动构造函数。
Definition box.h:150
friend std::ostream & operator<<(std::ostream &os, const Item &item)
将 Item 输出到流。
Definition box.h:255
~Item()
析构函数,释放内部堆内存。
Definition box.h:271
Item()
默认构造一个空 Item(ptr 为 nullptr)。
Definition box.h:127
const T & get() const
类型安全地获取存储值的引用(常量版本)。
Definition box.h:193
Item(const Item &other)
拷贝构造函数。
Definition box.h:143
T & get()
类型安全地获取存储值的引用(非常量版本)。
Definition box.h:162
const Item & operator=(const Item &other)
拷贝赋值运算符。
Definition box.h:222
std::string str() const
返回 Item 的字符串表示。
Definition box.h:265
const Item & operator=(Item &&other) noexcept
移动赋值运算符。
Definition box.h:238
const T & unsafe_get() const
不安全地获取存储值的引用(常量版本)。
Definition box.h:212
Item(T &&value)
从任意类型构造 Item(万能引用)。
Definition box.h:135
表示从 Item 或 Box 中获取类型不匹配或空值时发生的错误。
Definition csexc.h:105
定义 console 库使用的自定义异常类层次结构。
enable_if_string< T > repr(T &&value, std::ostream &os=std::cout)
输出字符串类型(std::string, const char* 等)的表示,带双引号。
Definition repr.h:79
std::string tiname(const std::type_info &ti)
获取类型信息的可读名称(跨平台 demangle)。
Definition repr.h:56
提供自定义字面量运算符,包括字符串字面量、时间字面量和格式化字符串字面量。
本库所有组件所在的顶层命名空间。
class console::Output print
全局输出对象,模仿 Python 的 print 函数。
@ T
Definition kb.h:72
提供字符串处理工具函数和格式化类。