xref: /aosp_15_r20/external/armnn/third-party/mapbox/README.md (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker# Mapbox Variant
2*89c4ff92SAndroid Build Coastguard Worker
3*89c4ff92SAndroid Build Coastguard WorkerAn header-only alternative to `boost::variant` for C++11 and C++14
4*89c4ff92SAndroid Build Coastguard Worker
5*89c4ff92SAndroid Build Coastguard Worker[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant)
6*89c4ff92SAndroid Build Coastguard Worker[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant)
7*89c4ff92SAndroid Build Coastguard Worker[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master&service=github)](https://coveralls.io/r/mapbox/variant?branch=master)
8*89c4ff92SAndroid Build Coastguard Worker
9*89c4ff92SAndroid Build Coastguard Worker## Introduction
10*89c4ff92SAndroid Build Coastguard Worker
11*89c4ff92SAndroid Build Coastguard WorkerVariant's basic building blocks are:
12*89c4ff92SAndroid Build Coastguard Worker
13*89c4ff92SAndroid Build Coastguard Worker- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
14*89c4ff92SAndroid Build Coastguard Worker- `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants
15*89c4ff92SAndroid Build Coastguard Worker- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type
16*89c4ff92SAndroid Build Coastguard Worker- `get<T>()` - a function to directly unwrap a variant's underlying type
17*89c4ff92SAndroid Build Coastguard Worker- `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant
18*89c4ff92SAndroid Build Coastguard Worker
19*89c4ff92SAndroid Build Coastguard Worker### Basic Usage - HTTP API Example
20*89c4ff92SAndroid Build Coastguard Worker
21*89c4ff92SAndroid Build Coastguard WorkerSuppose you want to represent a HTTP API response which is either a JSON result or an error:
22*89c4ff92SAndroid Build Coastguard Worker
23*89c4ff92SAndroid Build Coastguard Worker```c++
24*89c4ff92SAndroid Build Coastguard Workerstruct Result {
25*89c4ff92SAndroid Build Coastguard Worker  Json object;
26*89c4ff92SAndroid Build Coastguard Worker};
27*89c4ff92SAndroid Build Coastguard Worker
28*89c4ff92SAndroid Build Coastguard Workerstruct Error {
29*89c4ff92SAndroid Build Coastguard Worker  int32_t code;
30*89c4ff92SAndroid Build Coastguard Worker  string message;
31*89c4ff92SAndroid Build Coastguard Worker};
32*89c4ff92SAndroid Build Coastguard Worker```
33*89c4ff92SAndroid Build Coastguard Worker
34*89c4ff92SAndroid Build Coastguard WorkerYou can represent this at type level using a variant which is either an `Error` or a `Result`:
35*89c4ff92SAndroid Build Coastguard Worker
36*89c4ff92SAndroid Build Coastguard Worker```c++
37*89c4ff92SAndroid Build Coastguard Workerusing Response = variant<Error, Result>;
38*89c4ff92SAndroid Build Coastguard Worker
39*89c4ff92SAndroid Build Coastguard WorkerResponse makeRequest() {
40*89c4ff92SAndroid Build Coastguard Worker  return Error{501, "Not Implemented"};
41*89c4ff92SAndroid Build Coastguard Worker}
42*89c4ff92SAndroid Build Coastguard Worker
43*89c4ff92SAndroid Build Coastguard WorkerResponse ret = makeRequest();
44*89c4ff92SAndroid Build Coastguard Worker```
45*89c4ff92SAndroid Build Coastguard Worker
46*89c4ff92SAndroid Build Coastguard WorkerTo see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
47*89c4ff92SAndroid Build Coastguard Worker
48*89c4ff92SAndroid Build Coastguard Worker```c++
49*89c4ff92SAndroid Build Coastguard Workerret.match([] (Result r) { print(r.object); },
50*89c4ff92SAndroid Build Coastguard Worker          [] (Error e)  { print(e.message); });
51*89c4ff92SAndroid Build Coastguard Worker```
52*89c4ff92SAndroid Build Coastguard Worker
53*89c4ff92SAndroid Build Coastguard WorkerInstead of using the variant's convenience `.match` pattern matching function you can create a type visitor functor and use `apply_visitor` manually:
54*89c4ff92SAndroid Build Coastguard Worker
55*89c4ff92SAndroid Build Coastguard Worker```c++
56*89c4ff92SAndroid Build Coastguard Workerstruct ResponseVisitor {
57*89c4ff92SAndroid Build Coastguard Worker  void operator()(Result r) const {
58*89c4ff92SAndroid Build Coastguard Worker    print(r.object);
59*89c4ff92SAndroid Build Coastguard Worker  }
60*89c4ff92SAndroid Build Coastguard Worker
61*89c4ff92SAndroid Build Coastguard Worker  void operator()(Error e) const {
62*89c4ff92SAndroid Build Coastguard Worker    print(e.message);
63*89c4ff92SAndroid Build Coastguard Worker  }
64*89c4ff92SAndroid Build Coastguard Worker};
65*89c4ff92SAndroid Build Coastguard Worker
66*89c4ff92SAndroid Build Coastguard WorkerResponseVisitor visitor;
67*89c4ff92SAndroid Build Coastguard Workerapply_visitor(visitor, ret);
68*89c4ff92SAndroid Build Coastguard Worker```
69*89c4ff92SAndroid Build Coastguard Worker
70*89c4ff92SAndroid Build Coastguard WorkerIn both cases the compiler makes sure you handle all types the variant can represent at compile.
71*89c4ff92SAndroid Build Coastguard Worker
72*89c4ff92SAndroid Build Coastguard Worker### Recursive Variants - JSON Example
73*89c4ff92SAndroid Build Coastguard Worker
74*89c4ff92SAndroid Build Coastguard Worker[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
75*89c4ff92SAndroid Build Coastguard Worker
76*89c4ff92SAndroid Build Coastguard Worker```c++
77*89c4ff92SAndroid Build Coastguard Workerstruct String { string value; };
78*89c4ff92SAndroid Build Coastguard Workerstruct Number { double value; };
79*89c4ff92SAndroid Build Coastguard Workerstruct True   { };
80*89c4ff92SAndroid Build Coastguard Workerstruct False  { };
81*89c4ff92SAndroid Build Coastguard Workerstruct Null   { };
82*89c4ff92SAndroid Build Coastguard Workerstruct Array  { vector<?> values; };
83*89c4ff92SAndroid Build Coastguard Workerstruct Object { unordered_map<string, ?> values; };
84*89c4ff92SAndroid Build Coastguard Worker```
85*89c4ff92SAndroid Build Coastguard Worker
86*89c4ff92SAndroid Build Coastguard WorkerThis works for primitive types but how do we represent recursive types such as `Array` which can hold multiple elements and `Array` itself, too?
87*89c4ff92SAndroid Build Coastguard Worker
88*89c4ff92SAndroid Build Coastguard WorkerFor these use cases Variant provides a `recursive_wrapper` helper type which lets you express recursive Variants.
89*89c4ff92SAndroid Build Coastguard Worker
90*89c4ff92SAndroid Build Coastguard Worker```c++
91*89c4ff92SAndroid Build Coastguard Workerstruct String { string value; };
92*89c4ff92SAndroid Build Coastguard Workerstruct Number { double value; };
93*89c4ff92SAndroid Build Coastguard Workerstruct True   { };
94*89c4ff92SAndroid Build Coastguard Workerstruct False  { };
95*89c4ff92SAndroid Build Coastguard Workerstruct Null   { };
96*89c4ff92SAndroid Build Coastguard Worker
97*89c4ff92SAndroid Build Coastguard Worker// Forward declarations only
98*89c4ff92SAndroid Build Coastguard Workerstruct Array;
99*89c4ff92SAndroid Build Coastguard Workerstruct Object;
100*89c4ff92SAndroid Build Coastguard Worker
101*89c4ff92SAndroid Build Coastguard Workerusing Value = variant<String, Number, True, False, Null, recursive_wrapper<Array>, recursive_wrapper<Object>>;
102*89c4ff92SAndroid Build Coastguard Worker
103*89c4ff92SAndroid Build Coastguard Workerstruct Array {
104*89c4ff92SAndroid Build Coastguard Worker  vector<Value> values;
105*89c4ff92SAndroid Build Coastguard Worker};
106*89c4ff92SAndroid Build Coastguard Worker
107*89c4ff92SAndroid Build Coastguard Workerstruct Object {
108*89c4ff92SAndroid Build Coastguard Worker  unordered_map<string, Value> values;
109*89c4ff92SAndroid Build Coastguard Worker};
110*89c4ff92SAndroid Build Coastguard Worker```
111*89c4ff92SAndroid Build Coastguard Worker
112*89c4ff92SAndroid Build Coastguard WorkerFor walking the JSON representation you can again either create a `JSONVisitor`:
113*89c4ff92SAndroid Build Coastguard Worker
114*89c4ff92SAndroid Build Coastguard Worker```c++
115*89c4ff92SAndroid Build Coastguard Workerstruct JSONVisitor {
116*89c4ff92SAndroid Build Coastguard Worker
117*89c4ff92SAndroid Build Coastguard Worker  void operator()(Null) const {
118*89c4ff92SAndroid Build Coastguard Worker    print("null");
119*89c4ff92SAndroid Build Coastguard Worker  }
120*89c4ff92SAndroid Build Coastguard Worker
121*89c4ff92SAndroid Build Coastguard Worker  // same for all other JSON types
122*89c4ff92SAndroid Build Coastguard Worker};
123*89c4ff92SAndroid Build Coastguard Worker
124*89c4ff92SAndroid Build Coastguard WorkerJSONVisitor visitor;
125*89c4ff92SAndroid Build Coastguard Workerapply_visitor(visitor, json);
126*89c4ff92SAndroid Build Coastguard Worker```
127*89c4ff92SAndroid Build Coastguard Worker
128*89c4ff92SAndroid Build Coastguard WorkerOr use the convenience `.match` pattern matching function:
129*89c4ff92SAndroid Build Coastguard Worker
130*89c4ff92SAndroid Build Coastguard Worker```c++
131*89c4ff92SAndroid Build Coastguard Workerjson.match([] (Null) { print("null"); },
132*89c4ff92SAndroid Build Coastguard Worker           ...);
133*89c4ff92SAndroid Build Coastguard Worker```
134*89c4ff92SAndroid Build Coastguard Worker
135*89c4ff92SAndroid Build Coastguard WorkerTo summarize: use `recursive_wrapper` to represent recursive "tree-like" representations:
136*89c4ff92SAndroid Build Coastguard Worker
137*89c4ff92SAndroid Build Coastguard Worker```c++
138*89c4ff92SAndroid Build Coastguard Workerstruct Empty { };
139*89c4ff92SAndroid Build Coastguard Workerstruct Node;
140*89c4ff92SAndroid Build Coastguard Worker
141*89c4ff92SAndroid Build Coastguard Workerusing Tree = variant<Empty, recursive_wrapper<Node>>;
142*89c4ff92SAndroid Build Coastguard Worker
143*89c4ff92SAndroid Build Coastguard Workerstruct Node {
144*89c4ff92SAndroid Build Coastguard Worker  uint64_t value;
145*89c4ff92SAndroid Build Coastguard Worker}
146*89c4ff92SAndroid Build Coastguard Worker```
147*89c4ff92SAndroid Build Coastguard Worker
148*89c4ff92SAndroid Build Coastguard Worker### Advanced Usage Tips
149*89c4ff92SAndroid Build Coastguard Worker
150*89c4ff92SAndroid Build Coastguard WorkerCreating type aliases for variants is a great way to reduce repetition.
151*89c4ff92SAndroid Build Coastguard WorkerKeep in mind those type aliases are not checked at type level, though.
152*89c4ff92SAndroid Build Coastguard WorkerWe recommend creating a new type for all but basic variant usage:
153*89c4ff92SAndroid Build Coastguard Worker
154*89c4ff92SAndroid Build Coastguard Worker```c++
155*89c4ff92SAndroid Build Coastguard Worker// the compiler can't tell the following two apart
156*89c4ff92SAndroid Build Coastguard Workerusing APIResult = variant<Error, Result>;
157*89c4ff92SAndroid Build Coastguard Workerusing FilesystemResult = variant<Error, Result>;
158*89c4ff92SAndroid Build Coastguard Worker
159*89c4ff92SAndroid Build Coastguard Worker// new type
160*89c4ff92SAndroid Build Coastguard Workerstruct APIResult : variant<Error, Result> {
161*89c4ff92SAndroid Build Coastguard Worker  using Base = variant<Error, Result>;
162*89c4ff92SAndroid Build Coastguard Worker  using Base::Base;
163*89c4ff92SAndroid Build Coastguard Worker}
164*89c4ff92SAndroid Build Coastguard Worker```
165*89c4ff92SAndroid Build Coastguard Worker
166*89c4ff92SAndroid Build Coastguard Worker## Why use Mapbox Variant?
167*89c4ff92SAndroid Build Coastguard Worker
168*89c4ff92SAndroid Build Coastguard WorkerMapbox variant has the same speedy performance of `boost::variant` but is
169*89c4ff92SAndroid Build Coastguard Workerfaster to compile, results in smaller binaries, and has no dependencies.
170*89c4ff92SAndroid Build Coastguard Worker
171*89c4ff92SAndroid Build Coastguard WorkerFor example on OS X 10.9 with clang++ and libc++:
172*89c4ff92SAndroid Build Coastguard Worker
173*89c4ff92SAndroid Build Coastguard WorkerTest | Mapbox Variant | Boost Variant
174*89c4ff92SAndroid Build Coastguard Worker---- | -------------- | -------------
175*89c4ff92SAndroid Build Coastguard WorkerSize of pre-compiled header (release / debug) | 2.8/2.8 MB         | 12/15 MB
176*89c4ff92SAndroid Build Coastguard WorkerSize of simple program linking variant (release / debug)     | 8/24 K             | 12/40 K
177*89c4ff92SAndroid Build Coastguard WorkerTime to compile header     | 185 ms             |  675 ms
178*89c4ff92SAndroid Build Coastguard Worker
179*89c4ff92SAndroid Build Coastguard Worker(Numbers from an older version of Mapbox variant.)
180*89c4ff92SAndroid Build Coastguard Worker
181*89c4ff92SAndroid Build Coastguard Worker## Goals
182*89c4ff92SAndroid Build Coastguard Worker
183*89c4ff92SAndroid Build Coastguard WorkerMapbox `variant` has been a very valuable, lightweight alternative for apps
184*89c4ff92SAndroid Build Coastguard Workerthat can use c++11 or c++14 but that do not want a boost dependency.
185*89c4ff92SAndroid Build Coastguard WorkerMapbox `variant` has also been useful in apps that do depend on boost, like
186*89c4ff92SAndroid Build Coastguard Workermapnik, to help (slightly) with compile times and to majorly lessen dependence
187*89c4ff92SAndroid Build Coastguard Workeron boost in core headers. The original goal and near term goal is to maintain
188*89c4ff92SAndroid Build Coastguard Workerexternal API compatibility with `boost::variant` such that Mapbox `variant`
189*89c4ff92SAndroid Build Coastguard Workercan be a "drop in". At the same time the goal is to stay minimal: Only
190*89c4ff92SAndroid Build Coastguard Workerimplement the features that are actually needed in existing software. So being
191*89c4ff92SAndroid Build Coastguard Workeran "incomplete" implementation is just fine.
192*89c4ff92SAndroid Build Coastguard Worker
193*89c4ff92SAndroid Build Coastguard WorkerCurrently Mapbox variant doesn't try to be API compatible with the upcoming
194*89c4ff92SAndroid Build Coastguard Workervariant standard, because the standard is not finished and it would be too much
195*89c4ff92SAndroid Build Coastguard Workerwork. But we'll revisit this decision in the future if needed.
196*89c4ff92SAndroid Build Coastguard Worker
197*89c4ff92SAndroid Build Coastguard WorkerIf Mapbox variant is not for you, have a look at [these other
198*89c4ff92SAndroid Build Coastguard Workerimplementations](doc/other_implementations.md).
199*89c4ff92SAndroid Build Coastguard Worker
200*89c4ff92SAndroid Build Coastguard WorkerWant to know more about the upcoming standard? Have a look at our
201*89c4ff92SAndroid Build Coastguard Worker[overview](doc/standards_effort.md).
202*89c4ff92SAndroid Build Coastguard Worker
203*89c4ff92SAndroid Build Coastguard WorkerMost modern high-level languages provide ways to express sum types directly.
204*89c4ff92SAndroid Build Coastguard WorkerIf you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums.
205*89c4ff92SAndroid Build Coastguard Worker
206*89c4ff92SAndroid Build Coastguard Worker## Depends
207*89c4ff92SAndroid Build Coastguard Worker
208*89c4ff92SAndroid Build Coastguard Worker- Compiler supporting `-std=c++11` or `-std=c++14`
209*89c4ff92SAndroid Build Coastguard Worker
210*89c4ff92SAndroid Build Coastguard WorkerTested with:
211*89c4ff92SAndroid Build Coastguard Worker
212*89c4ff92SAndroid Build Coastguard Worker- g++-4.7
213*89c4ff92SAndroid Build Coastguard Worker- g++-4.8
214*89c4ff92SAndroid Build Coastguard Worker- g++-4.9
215*89c4ff92SAndroid Build Coastguard Worker- g++-5.2
216*89c4ff92SAndroid Build Coastguard Worker- clang++-3.5
217*89c4ff92SAndroid Build Coastguard Worker- clang++-3.6
218*89c4ff92SAndroid Build Coastguard Worker- clang++-3.7
219*89c4ff92SAndroid Build Coastguard Worker- clang++-3.8
220*89c4ff92SAndroid Build Coastguard Worker- clang++-3.9
221*89c4ff92SAndroid Build Coastguard Worker- Visual Studio 2015
222*89c4ff92SAndroid Build Coastguard Worker
223*89c4ff92SAndroid Build Coastguard Worker## Unit Tests
224*89c4ff92SAndroid Build Coastguard Worker
225*89c4ff92SAndroid Build Coastguard WorkerOn Unix systems compile and run the unit tests with `make test`.
226*89c4ff92SAndroid Build Coastguard Worker
227*89c4ff92SAndroid Build Coastguard WorkerOn Windows run `scripts/build-local.bat`.
228*89c4ff92SAndroid Build Coastguard Worker
229*89c4ff92SAndroid Build Coastguard Worker## Limitations
230*89c4ff92SAndroid Build Coastguard Worker
231*89c4ff92SAndroid Build Coastguard Worker- The `variant` can not hold references (something like `variant<int&>` is
232*89c4ff92SAndroid Build Coastguard Worker  not possible). You might want to try `std::reference_wrapper` instead.
233*89c4ff92SAndroid Build Coastguard Worker
234*89c4ff92SAndroid Build Coastguard Worker## Deprecations
235*89c4ff92SAndroid Build Coastguard Worker
236*89c4ff92SAndroid Build Coastguard Worker- The included implementation of `optional` is deprecated and will be removed
237*89c4ff92SAndroid Build Coastguard Worker  in a future version. See [issue #64](https://github.com/mapbox/variant/issues/64).
238*89c4ff92SAndroid Build Coastguard Worker- Old versions of the code needed visitors to derive from `static_visitor`.
239*89c4ff92SAndroid Build Coastguard Worker  This is not needed any more and marked as deprecated. The `static_visitor`
240*89c4ff92SAndroid Build Coastguard Worker  class will be removed in future versions.
241*89c4ff92SAndroid Build Coastguard Worker
242*89c4ff92SAndroid Build Coastguard Worker## Benchmarks
243*89c4ff92SAndroid Build Coastguard Worker
244*89c4ff92SAndroid Build Coastguard Worker    make bench
245*89c4ff92SAndroid Build Coastguard Worker
246*89c4ff92SAndroid Build Coastguard Worker## Check object sizes
247*89c4ff92SAndroid Build Coastguard Worker
248*89c4ff92SAndroid Build Coastguard Worker    make sizes /path/to/boost/variant.hpp
249