diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..0972e2d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +/html/ +/pdf/ diff --git a/doc/Jamfile b/doc/Jamfile new file mode 100644 index 0000000..1c26160 --- /dev/null +++ b/doc/Jamfile @@ -0,0 +1,23 @@ +# Copyright 2017, 2018 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import asciidoctor ; + +html variant.html : variant.adoc ; + +install html_ : variant.html : html ; + +pdf variant.pdf : variant.adoc ; +explicit variant.pdf ; + +install pdf_ : variant.pdf : pdf ; +explicit pdf_ ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : html_ ; +explicit boostrelease ; diff --git a/doc/variant-docinfo-footer.html b/doc/variant-docinfo-footer.html new file mode 100644 index 0000000..8e3910d --- /dev/null +++ b/doc/variant-docinfo-footer.html @@ -0,0 +1,5 @@ + diff --git a/doc/variant.adoc b/doc/variant.adoc new file mode 100644 index 0000000..e798473 --- /dev/null +++ b/doc/variant.adoc @@ -0,0 +1,23 @@ +//// +Copyright 2018 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +# Boost.Variant2: A never valueless variant type +Peter Dimov +:toc: left +:toclevels: 4 +:idprefix: +:docinfo: private-footer + +:leveloffset: +1 + +include::variant/overview.adoc[] +include::variant/reference.adoc[] +include::variant/copyright.adoc[] + +:leveloffset: -1 diff --git a/doc/variant/copyright.adoc b/doc/variant/copyright.adoc new file mode 100644 index 0000000..fd38de1 --- /dev/null +++ b/doc/variant/copyright.adoc @@ -0,0 +1,15 @@ +//// +Copyright 2018 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#copyright] +# Copyright and License +:idprefix: + +This documentation is copyright 2018 Peter Dimov and is distributed under +the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. diff --git a/doc/variant/overview.adoc b/doc/variant/overview.adoc new file mode 100644 index 0000000..0d681b2 --- /dev/null +++ b/doc/variant/overview.adoc @@ -0,0 +1,40 @@ +//// +Copyright 2018 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#overview] +# Overview +:idprefix: + +This library implements a type-safe discriminated union (variant) type, +`variant`, that almost conforms to the {cpp}17 Standard's +http://en.cppreference.com/w/cpp/utility/variant[`std::variant`]. The +main differences between the two are: + +* `variant` does not have a valueless-by-exception state; +* A converting constructor from, e.g. `variant` to + `variant` is provided as an extension; +* The reverse operation, going from `variant` to + `variant` is provided as the member function `subset`. + (This operation can throw if the current state of the variant cannot be + represented.) +* `variant` is not trivial when all contained types are trivial, as + mandated by {cpp}17. + +To avoid the valueless-by-exception state, this implementation falls +back to using double storage unless + +* one of the alternatives is the type `monostate`, +* one of the alternatives has a nonthrowing default constructor, or +* all the contained types are nothrow move constructible. + +If the first two bullets don't hold, but the third does, the variant uses +single storage, but `emplace` constructs a temporary and moves it into place +if the construction of the object can throw. In case this is undesirable, one +can force `emplace` into always constructing in-place by adding `monostate` as +one of the alternatives. diff --git a/doc/variant/reference.adoc b/doc/variant/reference.adoc new file mode 100644 index 0000000..39617cd --- /dev/null +++ b/doc/variant/reference.adoc @@ -0,0 +1,402 @@ +//// +Copyright 2018 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#reference] +# Reference +:idprefix: ref_ + +## + +### Synopsis + +``` +namespace boost { +namespace variant2 { + +// in_place_type + +template struct in_place_type_t {}; +template constexpr in_place_type_t in_place_type{}; + +// in_place_index + +template struct in_place_index_t {}; +template constexpr in_place_index_t in_place_index{}; + +// variant + +template class variant; + +// variant_size + +template struct variant_size {}; + +template struct variant_size: variant_size {}; +template struct variant_size: variant_size {}; +template struct variant_size: variant_size {}; + +template + inline constexpr size_t variant_size_v = variant_size::value; + +template + struct variant_size>: + std::integral_constant {}; + +// variant_alternative + +template struct variant_alternative {}; + +template struct variant_alternative; +template struct variant_alternative; +template struct variant_alternative; + +template + using variant_alternative_t = typename variant_alternative::type; + +template + struct variant_alternative>; + +// variant_npos + +constexpr std::size_t variant_npos = -1; + +// holds_alternative + +template + constexpr bool holds_alternative(const variant&) noexcept; + +// get + +template + constexpr variant_alternative_t>& + get(variant&); +template + constexpr variant_alternative_t>&& + get(variant&&); +template + constexpr const variant_alternative_t>& + get(const variant&); +template + constexpr const variant_alternative_t>&& + get(const variant&&); + +template + constexpr U& get(variant&); +template + constexpr U&& get(variant&&); +template + constexpr const U& get(const variant&); +template + constexpr const U&& get(const variant&&); + +// get_if + +template + constexpr add_pointer_t>> + get_if(variant*) noexcept; +template + constexpr add_pointer_t>> + get_if(const variant*) noexcept; +template + constexpr add_pointer_t + get_if(variant*) noexcept; +template + constexpr add_pointer_t + get_if(const variant*) noexcept; + +// relational operators + +template + constexpr bool operator==(const variant&, const variant&); +template + constexpr bool operator!=(const variant&, const variant&); +template + constexpr bool operator<(const variant&, const variant&); +template + constexpr bool operator>(const variant&, const variant&); +template + constexpr bool operator<=(const variant&, const variant&); +template + constexpr bool operator>=(const variant&, const variant&); + +// visit + +template + constexpr /*see below*/ visit(F&&, V&&...); + +// monostate + +struct monostate {}; + +constexpr bool operator==(monostate, monostate) noexcept { return true; } +constexpr bool operator!=(monostate, monostate) noexcept { return false; } +constexpr bool operator<(monostate, monostate) noexcept { return false; } +constexpr bool operator>(monostate, monostate) noexcept { return false; } +constexpr bool operator<=(monostate, monostate) noexcept { return true; } +constexpr bool operator>=(monostate, monostate) noexcept { return true; } + +// swap + +template + void swap(variant&, variant&) noexcept( see below ); + +// bad_variant_access + +class bad_variant_access; + +} // namespace variant2 +} // namespace boost +``` + +### variant + +``` +namespace boost { +namespace variant2 { + +template class variant +{ +public: + + // constructors + + constexpr variant() noexcept( /*see below*/ ); + + constexpr variant(variant const &) noexcept( /*see below*/ ); + constexpr variant(variant&&) noexcept( /*see below*/ ); + + template + constexpr variant(U&&) noexcept( /*see below*/ ); + + template + constexpr explicit variant(in_place_type_t, A&&...); + template + constexpr explicit variant(in_place_type_t, initializer_list, + A&&...); + + template + constexpr explicit variant(in_place_index_t, A&&...); + template + constexpr explicit variant(in_place_index_t, initializer_list, + A&&...); + + // destructor + + ~variant(); + + // assignment + + constexpr variant& operator=(variant const &) noexcept( /*see below*/ ); + constexpr variant& operator=(variant&&) noexcept( /*see below*/ ); + + template constexpr variant& operator=(U&&) noexcept( /*see below*/ ); + + // modifiers + + template + constexpr U& emplace(A&&...); + template + constexpr T& emplace(initializer_list, A&&...); + + template + constexpr variant_alternative_t>& + emplace(A&&...); + template + constexpr variant_alternative_t>& + emplace(initializer_list, A&&...); + + // value status + + constexpr bool valueless_by_exception() const noexcept; + constexpr size_t index() const noexcept; + + // swap + + void swap(variant&) noexcept( /*see below*/ ); + + // converting constructors (extension) + + template variant( variant const& r ) + noexcept( /*see below*/ ); + + template variant( variant&& r ) + noexcept( /*see below*/ ); + + // subset (extension) + + template constexpr variant subset() & ; + template constexpr variant subset() && ; + template constexpr variant subset() const& ; + template constexpr variant subset() const&& ; +}; + +} // namespace variant2 +} // namespace boost +``` + +#### Constructors + +``` +constexpr variant() noexcept(is_nothrow_default_constructible_v); +``` +[none] +* {blank} ++ +Effects: :: Constructs a `variant` holding a value-initialized value of + type `T0`. +Ensures: :: `index() == 0`. +Throws: :: Any exception thrown by the value-initialization of `T0`. +Remarks: :: This function does not participate in overload resolution unless + `is_default_constructible_v` is `true`. + +``` +constexpr variant(variant const & w) + noexcept( mp_all...>::value ); +``` +[none] +* {blank} ++ +Effects: :: Initializes the variant to hold the same alternative and value as + `w`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: This function does not participate in overload resolution unless + `is_copy_constructible_v` is `true` for all `i`. + +``` +constexpr variant(variant&& w) + noexcept( mp_all...>::value ); +``` +[none] +* {blank} ++ +Effects: :: Initializes the variant to hold the same alternative and value as + `w`. +Throws: :: Any exception thrown by the move-initialization of the contained + value. +Remarks: :: This function does not participate in overload resolution unless + `is_move_constructible_v` is `true` for all `i`. + +``` +template constexpr variant(U&& u) noexcept(/*see below*/); +``` +[none] +* {blank} ++ +Let `Tj` be a type that is determined as follows: build an imaginary function +`FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by +overload resolution for the expression `FUN(std::forward(u))` defines the +alternative `Tj` which is the type of the contained value after construction. + +Effects: :: Initializes `*this` to hold the alternative type `Tj` and + initializes the contained value from `std::forward(u)`. +Ensures: :: `holds_alternative(*this)`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: The expression inside `noexcept` is equivalent to +`is_nothrow_constructible_v`. This function does not participate in +overload resolution unless +- `sizeof...(T)` is nonzero, +- `is_same_v, variant>` is `false`, +- `remove_cvref_t` is neither a specialization of `in_place_type_t` nor a +specialization of `in_place_index_t`, +- `is_constructible_v` is `true`, and +- the expression `FUN(std::forward(u))` is well-formed. + +``` +template + constexpr explicit variant(in_place_type_t, A&&... a); +``` +[none] +* {blank} ++ +Effects: :: Initializes the contained value of type `U` with the arguments + `std::forward(a)...`. +Ensures: :: `holds_alternative(*this)`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: This function does not participate in overload resolution unless + there is exactly one occurrence of `U` in `T...` and + `is_constructible_v` is true. + +``` +template + constexpr explicit variant(in_place_type_t, initializer_list il, + A&&... a); +``` +[none] +* {blank} ++ +Effects: :: Initializes the contained value of type `U` with the arguments `il`, + `std::forward(a)...`. +Ensures: :: `holds_alternative(*this)`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: This function does not participate in overload resolution unless + there is exactly one occurrence of `U` in `T...` and + `is_constructible_v&, A...>` is `true`. + +``` +template + constexpr explicit variant(in_place_index_t, A&&... a); +``` +[none] +* {blank} ++ +Effects: :: Initializes the contained value of type `TI` with the arguments + `std::forward(a)...`. +Ensures: :: `index() == I`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: This function does not participate in overload resolution unless + `I < sizeof...(T)` and `is_constructible_v` is `true`. + +``` +template + constexpr explicit variant(in_place_index_t, initializer_list il, + A&&... a); +``` +[none] +* {blank} ++ +Effects: :: Initializes the contained value of type `TI` with the arguments + `il`, `std::forward(a)...`. +Ensures: :: `index() == I`. +Throws: :: Any exception thrown by the initialization of the contained value. +Remarks: :: This function does not participate in overload resolution unless + `I < sizeof...(Types)` and + `is_constructible_v&, A...>` is `true`. + +#### Destructor + +``` +~variant(); +``` +[none] +* {blank} ++ +Effects: :: Destroys the currently contained value. + +#### Assignment + +``` +constexpr variant& operator=(const variant& rhs) + noexcept( mp_all..., + std::is_nothrow_copy_assignable...>::value ); +``` +[none] +* {blank} ++ +Let `j` be `rhs.index()`. + +Effects: :: +- If `index() == j`, assigns the value contained in `rhs` to the value + contained in `*this`. +- Otherwise, equivalent to `emplace(get(rhs))`. +Returns: :: `*this`. +Ensures: :: `index() == rhs.index()`. +Remarks: :: This operator does not participate in overload resolution unless + `is_copy_constructible_v && is_copy_assignable_v` is `true` for all + `i`. +