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[](https://travis-ci.org/mapbox/variant) 6*89c4ff92SAndroid Build Coastguard Worker[](https://ci.appveyor.com/project/Mapbox/variant) 7*89c4ff92SAndroid Build Coastguard Worker[](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