aboutsummaryrefslogtreecommitdiff
path: root/third-party/mapbox/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'third-party/mapbox/README.md')
-rw-r--r--third-party/mapbox/README.md248
1 files changed, 248 insertions, 0 deletions
diff --git a/third-party/mapbox/README.md b/third-party/mapbox/README.md
new file mode 100644
index 0000000000..6bf97f0c45
--- /dev/null
+++ b/third-party/mapbox/README.md
@@ -0,0 +1,248 @@
+# Mapbox Variant
+
+An header-only alternative to `boost::variant` for C++11 and C++14
+
+[![Build Status](https://secure.travis-ci.org/mapbox/variant.svg)](https://travis-ci.org/mapbox/variant)
+[![Build status](https://ci.appveyor.com/api/projects/status/v9tatx21j1k0fcgy)](https://ci.appveyor.com/project/Mapbox/variant)
+[![Coverage Status](https://coveralls.io/repos/mapbox/variant/badge.svg?branch=master&service=github)](https://coveralls.io/r/mapbox/variant?branch=master)
+
+## Introduction
+
+Variant's basic building blocks are:
+
+- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
+- `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants
+- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type
+- `get<T>()` - a function to directly unwrap a variant's underlying type
+- `.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
+
+### Basic Usage - HTTP API Example
+
+Suppose you want to represent a HTTP API response which is either a JSON result or an error:
+
+```c++
+struct Result {
+ Json object;
+};
+
+struct Error {
+ int32_t code;
+ string message;
+};
+```
+
+You can represent this at type level using a variant which is either an `Error` or a `Result`:
+
+```c++
+using Response = variant<Error, Result>;
+
+Response makeRequest() {
+ return Error{501, "Not Implemented"};
+}
+
+Response ret = makeRequest();
+```
+
+To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
+
+```c++
+ret.match([] (Result r) { print(r.object); },
+ [] (Error e) { print(e.message); });
+```
+
+Instead of using the variant's convenience `.match` pattern matching function you can create a type visitor functor and use `apply_visitor` manually:
+
+```c++
+struct ResponseVisitor {
+ void operator()(Result r) const {
+ print(r.object);
+ }
+
+ void operator()(Error e) const {
+ print(e.message);
+ }
+};
+
+ResponseVisitor visitor;
+apply_visitor(visitor, ret);
+```
+
+In both cases the compiler makes sure you handle all types the variant can represent at compile.
+
+### Recursive Variants - JSON Example
+
+[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
+
+```c++
+struct String { string value; };
+struct Number { double value; };
+struct True { };
+struct False { };
+struct Null { };
+struct Array { vector<?> values; };
+struct Object { unordered_map<string, ?> values; };
+```
+
+This works for primitive types but how do we represent recursive types such as `Array` which can hold multiple elements and `Array` itself, too?
+
+For these use cases Variant provides a `recursive_wrapper` helper type which lets you express recursive Variants.
+
+```c++
+struct String { string value; };
+struct Number { double value; };
+struct True { };
+struct False { };
+struct Null { };
+
+// Forward declarations only
+struct Array;
+struct Object;
+
+using Value = variant<String, Number, True, False, Null, recursive_wrapper<Array>, recursive_wrapper<Object>>;
+
+struct Array {
+ vector<Value> values;
+};
+
+struct Object {
+ unordered_map<string, Value> values;
+};
+```
+
+For walking the JSON representation you can again either create a `JSONVisitor`:
+
+```c++
+struct JSONVisitor {
+
+ void operator()(Null) const {
+ print("null");
+ }
+
+ // same for all other JSON types
+};
+
+JSONVisitor visitor;
+apply_visitor(visitor, json);
+```
+
+Or use the convenience `.match` pattern matching function:
+
+```c++
+json.match([] (Null) { print("null"); },
+ ...);
+```
+
+To summarize: use `recursive_wrapper` to represent recursive "tree-like" representations:
+
+```c++
+struct Empty { };
+struct Node;
+
+using Tree = variant<Empty, recursive_wrapper<Node>>;
+
+struct Node {
+ uint64_t value;
+}
+```
+
+### Advanced Usage Tips
+
+Creating type aliases for variants is a great way to reduce repetition.
+Keep in mind those type aliases are not checked at type level, though.
+We recommend creating a new type for all but basic variant usage:
+
+```c++
+// the compiler can't tell the following two apart
+using APIResult = variant<Error, Result>;
+using FilesystemResult = variant<Error, Result>;
+
+// new type
+struct APIResult : variant<Error, Result> {
+ using Base = variant<Error, Result>;
+ using Base::Base;
+}
+```
+
+## Why use Mapbox Variant?
+
+Mapbox variant has the same speedy performance of `boost::variant` but is
+faster to compile, results in smaller binaries, and has no dependencies.
+
+For example on OS X 10.9 with clang++ and libc++:
+
+Test | Mapbox Variant | Boost Variant
+---- | -------------- | -------------
+Size of pre-compiled header (release / debug) | 2.8/2.8 MB | 12/15 MB
+Size of simple program linking variant (release / debug) | 8/24 K | 12/40 K
+Time to compile header | 185 ms | 675 ms
+
+(Numbers from an older version of Mapbox variant.)
+
+## Goals
+
+Mapbox `variant` has been a very valuable, lightweight alternative for apps
+that can use c++11 or c++14 but that do not want a boost dependency.
+Mapbox `variant` has also been useful in apps that do depend on boost, like
+mapnik, to help (slightly) with compile times and to majorly lessen dependence
+on boost in core headers. The original goal and near term goal is to maintain
+external API compatibility with `boost::variant` such that Mapbox `variant`
+can be a "drop in". At the same time the goal is to stay minimal: Only
+implement the features that are actually needed in existing software. So being
+an "incomplete" implementation is just fine.
+
+Currently Mapbox variant doesn't try to be API compatible with the upcoming
+variant standard, because the standard is not finished and it would be too much
+work. But we'll revisit this decision in the future if needed.
+
+If Mapbox variant is not for you, have a look at [these other
+implementations](doc/other_implementations.md).
+
+Want to know more about the upcoming standard? Have a look at our
+[overview](doc/standards_effort.md).
+
+Most modern high-level languages provide ways to express sum types directly.
+If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums.
+
+## Depends
+
+- Compiler supporting `-std=c++11` or `-std=c++14`
+
+Tested with:
+
+- g++-4.7
+- g++-4.8
+- g++-4.9
+- g++-5.2
+- clang++-3.5
+- clang++-3.6
+- clang++-3.7
+- clang++-3.8
+- clang++-3.9
+- Visual Studio 2015
+
+## Unit Tests
+
+On Unix systems compile and run the unit tests with `make test`.
+
+On Windows run `scripts/build-local.bat`.
+
+## Limitations
+
+- The `variant` can not hold references (something like `variant<int&>` is
+ not possible). You might want to try `std::reference_wrapper` instead.
+
+## Deprecations
+
+- The included implementation of `optional` is deprecated and will be removed
+ in a future version. See [issue #64](https://github.com/mapbox/variant/issues/64).
+- Old versions of the code needed visitors to derive from `static_visitor`.
+ This is not needed any more and marked as deprecated. The `static_visitor`
+ class will be removed in future versions.
+
+## Benchmarks
+
+ make bench
+
+## Check object sizes
+
+ make sizes /path/to/boost/variant.hpp