1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
# STC [cbox](../include/stc/cbox.h): Smart Pointer (Boxed object)
**cbox** is a A box is a smart pointer to a heap allocated value of type X. A **cbox** can
be empty. The *cbox_X_cmp()*, *cbox_X_drop()* methods are defined based on the `i_cmp`
and `i_valdrop` macros specified. Use *cbox_X_clone(p)* to make a deep copy, which uses the
`i_valfrom` macro if defined.
When declaring a container of **cbox** values, define `i_val_arcbox` with the
cbox type instead of defining `i_val`. This will auto-set `i_valdrop`, `i_valfrom`, and `i_cmp` using
functions defined by the specified **cbox**.
See similar c++ class [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) for a functional reference, or Rust [std::boxed::Box](https://doc.rust-lang.org/std/boxed/struct.Box.html)
## Header file and declaration
```c
#define i_val // value: REQUIRED
#define i_cmp // three-way compare two i_val* : REQUIRED IF i_val is a non-integral type
#define i_valdrop // destroy value func - defaults to empty destruct
#define i_valraw // convertion type
#define i_valfrom // create from raw/clone func - REQUIRED if i_valdrop is defined,
// unless 'i_opt c_no_clone' is defined.
#define i_valto // to-raw func.
#define i_tag // type name tag, defaults to i_val
#include <stc/cbox.h>
```
`X` should be replaced by the value of `i_tag` in all of the following documentation.
Define `i_opt` with `c_no_cmp` if comparison between i_val's is not needed/available. Will then
compare the pointer addresses when used. Additionally, `c_no_clone` or `i_is_fwd` may be defined.
## Methods
```c
cbox_X cbox_X_init(); // return an empty cbox
cbox_X cbox_X_make(i_valraw raw); // create owned value from raw type, if defined.
cbox_X cbox_X_from(i_val val); // allocate new heap object with val. Take ownership of val.
cbox_X cbox_X_from_ptr(i_val* p); // create a cbox from a pointer. Takes ownership of p.
cbox_X cbox_X_clone(cbox_X other); // return deep copied clone
cbox_X cbox_X_move(cbox_X* self); // transfer ownership to another cbox.
void cbox_X_take(cbox_X* self, cbox_X other); // take ownership of other.
void cbox_X_copy(cbox_X* self, cbox_X other); // deep copy to self
void cbox_X_drop(cbox_X* self); // destruct the contained object and free's it.
void cbox_X_reset(cbox_X* self);
void cbox_X_reset_from(cbox_X* self, i_val val); // assign new cbox with value. Takes ownership of val.
uint64_t cbox_X_value_hash(const i_val* x); // hash value
int cbox_X_value_cmp(const i_val* x, const i_val* y); // compares pointer addresses if 'i_opt c_no_cmp'
// is defined. Otherwise uses 'i_cmp' or default compare.
bool cbox_X_value_eq(const i_val* x, const i_val* y); // cbox_X_value_cmp == 0
```
## Types and constants
| Type name | Type definition | Used to represent... |
|:-------------------|:--------------------------------|:------------------------|
| `cbox_null` | `{NULL}` | Init nullptr const |
| `cbox_X` | `struct { cbox_X_value* get; }` | The cbox type |
| `cbox_X_value` | `i_val` | The cbox element type |
## Example
```c
#include <stdio.h>
void int_drop(int* x) {
printf("\n drop %d", *x);
}
#define i_type IBox
#define i_val int
#define i_valdrop int_drop // optional func, just to display elements destroyed
#define i_valfrom(x) x // must specify because i_valdrop was defined.
#include <stc/cbox.h>
#define i_type ISet
#define i_key_arcbox IBox // NB: use i_key_arcbox instead of i_key
#include <stc/csset.h> // ISet : std::set<std::unique_ptr<int>>
#define i_type IVec
#define i_val_arcbox IBox // NB: use i_val_arcbox instead of i_val
#include <stc/cvec.h> // IVec : std::vector<std::unique_ptr<int>>
int main()
{
c_auto (IVec, vec) // declare and init vec, call drop at scope exit
c_auto (ISet, set) // similar
{
c_apply(v, IVec_push(&vec, v), IBox, {
IBox_from(2021), IBox_from(2012),
IBox_from(2022), IBox_from(2015),
});
printf("vec:");
c_foreach (i, IVec, vec)
printf(" %d", *i.ref->get);
// add odd numbers from vec to set
c_foreach (i, IVec, vec)
if (*i.ref->get & 1)
ISet_insert(&set, IBox_clone(*i.ref));
// pop the two last elements in vec
IVec_pop(&vec);
IVec_pop(&vec);
printf("\nvec:");
c_foreach (i, IVec, vec)
printf(" %d", *i.ref->get);
printf("\nset:");
c_foreach (i, ISet, set)
printf(" %d", *i.ref->get);
}
}
```
Output:
```
vec: 2021 2012 2022 2015
drop 2015
drop 2022
vec: 2021 2012
set: 2015 2021
drop 2021
drop 2015
drop 2012
drop 2021
```
|