// // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) // // 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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_DETAIL_VARIANT_HPP #define BOOST_BEAST_DETAIL_VARIANT_HPP #include #include #include #include #include namespace boost { namespace beast { namespace detail { // This simple variant gets the job done without // causing too much trouble with template depth: // // * Always allows an empty state I==0 // * emplace() and get() support 1-based indexes only // * Basic exception guarantee // * Max 255 types // template class variant { typename std::aligned_storage< max_sizeof(), max_alignof() >::type buf_; unsigned char i_ = 0; template using type = typename std::tuple_element< I , std::tuple>::type; template using C = std::integral_constant; public: variant() = default; ~variant() { if(i_) destroy(C<0>{}); } // 0 = empty unsigned char index() const { return i_; } // moved-from object becomes empty variant(variant&& other) { i_ = other.move(&buf_, C<0>{}); } variant(variant const& other) { i_ = other.copy(&buf_, C<0>{}); } // moved-from object becomes empty variant& operator=(variant&& other) { if(i_ != 0) destroy(C<0>{}); i_ = other.move(&buf_, C<0>{}); return *this; } variant& operator=(variant const& other) { if(i_ != 0) destroy(C<0>{}); i_ = other.copy(&buf_, C<0>{}); return *this; } template void emplace(Args&&... args) { if(i_ != 0) destroy(C<0>{}); new(&buf_) type( std::forward(args)...); i_ = I; } template type& get() { BOOST_ASSERT(i_ == I); return *reinterpret_cast< type*>(&buf_); } template type const& get() const { BOOST_ASSERT(i_ == I); return *reinterpret_cast< type const*>(&buf_); } void reset() { if(i_ == 0) return; destroy(C<0>{}); } private: void destroy(C) { return; } template void destroy(C) { if(i_ == I+1) { using T = type; get().~T(); i_ = 0; return; } destroy(C{}); } unsigned char move(void*, C) { return 0; } template unsigned char move(void* dest, C) { if(i_ == I+1) { using T = type; new(dest) T{std::move(get())}; get().~T(); i_ = 0; return I+1; } return move(dest, C{}); } unsigned char copy(void*, C) const { return 0; } template unsigned char copy(void* dest, C) const { if(i_ == I+1) { using T = type; auto const& t = get(); new(dest) T{t}; return I+1; } return copy(dest, C{}); } }; } // detail } // beast } // boost #endif