diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 11916ee38..1171dd84c 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -90,6 +90,9 @@ QT_WARNING_POP #if __cplusplus >= 201402L using namespace std::chrono_literals; +#else +#include "../vmisc/bpstd/chrono.hpp" +using namespace bpstd::literals::chrono_literals; #endif namespace @@ -358,7 +361,7 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : break; } - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(100ms); } } @@ -388,11 +391,7 @@ VPMainWindow::VPMainWindow(const VPCommandLinePtr &cmd, QWidget *parent) : if (m_cmd->IsGuiEnabled()) { -#if __cplusplus >= 201402L QTimer::singleShot(1s, this, &VPMainWindow::SetDefaultGUILanguage); -#else - QTimer::singleShot(1000, this, &VPMainWindow::SetDefaultGUILanguage); -#endif } } diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index 59429a0f0..1623cd5b2 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -76,6 +76,9 @@ #if __cplusplus >= 201402L using namespace std::chrono_literals; +#else +#include "../vmisc/bpstd/chrono.hpp" +using namespace bpstd::literals::chrono_literals; #endif #if defined(Q_OS_MAC) @@ -242,11 +245,7 @@ TMainWindow::TMainWindow(QWidget *parent) if (MApplication::VApp()->IsAppInGUIMode()) { -#if __cplusplus >= 201402L QTimer::singleShot(1s, this, &TMainWindow::SetDefaultGUILanguage); -#else - QTimer::singleShot(1000, this, &TMainWindow::SetDefaultGUILanguage); -#endif } } diff --git a/src/app/valentina/dialogs/dialoglayoutprogress.cpp b/src/app/valentina/dialogs/dialoglayoutprogress.cpp index 65e63c19a..953dcf21a 100644 --- a/src/app/valentina/dialogs/dialoglayoutprogress.cpp +++ b/src/app/valentina/dialogs/dialoglayoutprogress.cpp @@ -41,6 +41,9 @@ #if __cplusplus >= 201402L using namespace std::chrono_literals; +#else +#include "../vmisc/bpstd/chrono.hpp" +using namespace bpstd::literals::chrono_literals; #endif //--------------------------------------------------------------------------------------------------------------------- @@ -85,11 +88,7 @@ DialogLayoutProgress::DialogLayoutProgress(QElapsedTimer timer, qint64 timeout, m_progressTimer->stop(); } }); -#if __cplusplus >= 201402L m_progressTimer->start(1s); -#else - m_progressTimer->start(1000); -#endif } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/dialogs/vwidgetdetails.cpp b/src/app/valentina/dialogs/vwidgetdetails.cpp index 8b6234522..bc9e0f0ea 100644 --- a/src/app/valentina/dialogs/vwidgetdetails.cpp +++ b/src/app/valentina/dialogs/vwidgetdetails.cpp @@ -41,6 +41,9 @@ #if __cplusplus >= 201402L using namespace std::chrono_literals; +#else +#include "../vmisc/bpstd/chrono.hpp" +using namespace bpstd::literals::chrono_literals; #endif namespace @@ -93,11 +96,7 @@ void VWidgetDetails::UpdateList() // The filling table is a very expensive operation. This optimization will postpone it. // Each time a new request happen we will wait 800 ms before calling it. If at this time a new request will arrive // we will wait 800 ms more. And so on, until nothing happens within 800ms. -#if __cplusplus >= 201402L m_updateListTimer->start(800ms); -#else - m_updateListTimer->start(800); -#endif } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index 8e7b76c73..1165c2bf8 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -216,6 +216,9 @@ #if __cplusplus >= 201402L using namespace std::chrono_literals; +#else +#include "../vmisc/bpstd/chrono.hpp" +using namespace bpstd::literals::chrono_literals; #endif QT_WARNING_PUSH @@ -471,11 +474,7 @@ MainWindow::MainWindow(QWidget *parent) if (VApplication::IsGUIMode()) { -#if __cplusplus >= 201402L QTimer::singleShot(1s, this, &MainWindow::SetDefaultGUILanguage); -#else - QTimer::singleShot(1000, this, &MainWindow::SetDefaultGUILanguage); -#endif } } @@ -2140,11 +2139,7 @@ void MainWindow::MeasurementsChanged(const QString &path) { m_mChanges = true; m_mChangesAsked = false; -#if __cplusplus >= 201402L m_measurementsSyncTimer->start(1500ms); -#else - m_measurementsSyncTimer->start(1500); -#endif } else { @@ -2154,11 +2149,7 @@ void MainWindow::MeasurementsChanged(const QString &path) { m_mChanges = true; m_mChangesAsked = false; -#if __cplusplus >= 201402L m_measurementsSyncTimer->start(1500ms); -#else - m_measurementsSyncTimer->start(1500); -#endif break; } diff --git a/src/libs/vmisc/bpstd/LICENSE b/src/libs/vmisc/bpstd/LICENSE new file mode 100644 index 000000000..d412ec7ac --- /dev/null +++ b/src/libs/vmisc/bpstd/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Matthew Rodusek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/libs/vmisc/bpstd/any.hpp b/src/libs/vmisc/bpstd/any.hpp new file mode 100644 index 000000000..8c2a49bd6 --- /dev/null +++ b/src/libs/vmisc/bpstd/any.hpp @@ -0,0 +1,935 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file any.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_ANY_HPP +#define BPSTD_ANY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "type_traits.hpp" // enable_if_t, is_* +#include "utility.hpp" // in_place_type_t, move, forward + +#include // std::bad_cast, std::type_info +#include // std::initializer_list +#include // placement-new +#include // assert + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + class any; + + //============================================================================ + // class : bad_any_cast + //============================================================================ + + class bad_any_cast : public std::bad_cast + { + const char* what() const noexcept override; + }; + + //============================================================================ + // class : any + //============================================================================ + + ////////////////////////////////////////////////////////////////////////////// + /// \brief An object that can hold values of any type via type-erasure + /// + /// The class any describes a type-safe container for single values of any + /// type. + /// + /// 1) An object of class any stores an instance of any type that satisfies + /// the constructor requirements or is empty, and this is referred to as the + /// state of the class any object. The stored instance is called the + /// contained object. Two states are equivalent if they are either both + /// empty or if both are not empty and if the contained objects are + /// equivalent. + /// + /// 2) The non-member any_cast functions provide type-safe access to the + /// contained object. + /// + /// This implementation uses small-buffer optimization to avoid dynamic + /// memory if the object is below a (4 * sizeof(void*)) + ////////////////////////////////////////////////////////////////////////////// + class any + { + //-------------------------------------------------------------------------- + // Constructors / Destructor / Assignment + //-------------------------------------------------------------------------- + public: + + /// \brief Constructs an any instance that does not contain any value + any() noexcept; + + /// \brief Moves an any instance by moving the stored underlying value + /// + /// \post \p other is left valueless + /// + /// \param other the other instance to move + any(any&& other) noexcept; + + /// \brief Copies an any instance by copying the stored underlying value + /// + /// \param other the other instance to copy + any(const any& other); + + /// \brief Constructs this any using \p value for the underlying instance + /// + /// \param value the value to construct this any out of + template,any>::value && + is_copy_constructible>::value>> + // cppcheck-suppress noExplicitConstructor + any(ValueType&& value); + + /// \brief Constructs an 'any' of type ValueType by forwarding \p args to + /// its constructor + /// + /// \note This constructor only participates in overload resolution if + /// ValueType is constructible from \p args + /// + /// \param args the arguments to forward to ValueType's constructor + template,Args...>::value && + is_copy_constructible>::value>> + explicit any(in_place_type_t, Args&&...args); + + /// \brief Constructs an 'any' of type ValueType by forwarding \p args to + /// its constructor + /// + /// \note This constructor only participates in overload resolution if + /// ValueType is constructible from \p args + /// + /// \param il an initializer_list of arguments + /// \param args the arguments to forward to ValueType's constructor + template,std::initializer_list,Args...>::value && + is_copy_constructible>::value>> + explicit any(in_place_type_t, + std::initializer_list il, + Args&&...args); + + //-------------------------------------------------------------------------- + + ~any(); + + //-------------------------------------------------------------------------- + + /// \brief Assigns the contents of \p other to this any + /// + /// \param other the other any to move + /// \return reference to \c (*this) + any& operator=(any&& other) noexcept; + + /// \brief Assigns the contents of \p other to this any + /// + /// \param other the other any to copy + /// \return reference to \c (*this) + any& operator=(const any& other); + + /// \brief Assigns \p value to this any + /// + /// \param value the value to assign + /// \return reference to \c (*this) + template,any>::value && + is_copy_constructible>::value>> + any& operator=(ValueType&& value); + + //-------------------------------------------------------------------------- + // Modifiers + //-------------------------------------------------------------------------- + public: + + /// \{ + /// \brief Emplaces a \c ValueType into this any, destroying the previous + /// value if it contained one + /// + /// \tparam ValueType the type to construct + /// \param args the arguments to forward to \c ValueType's constructor + /// \return reference to the constructed value + template,Args...>::value && + is_copy_constructible>::value>> + decay_t& emplace(Args&&...args); + template,std::initializer_list,Args...>::value && + is_copy_constructible>::value>> + decay_t& emplace(std::initializer_list il, Args&&...args ); + /// \} + + /// \brief Destroys the underlying stored value, leaving this any + /// empty. + void reset() noexcept; + + /// \brief Swaps the contents of \c this with \p other + /// + /// \post \p other contains the old contents of \c this, and \c this + /// contains the old contents of \p other + /// + /// \param other the other any to swap contents with + void swap(any& other) noexcept; + + //-------------------------------------------------------------------------- + // Observers + //-------------------------------------------------------------------------- + public: + + /// \brief Checks whether this any contains a value + /// + /// \return \c true if this contains a value + bool has_value() const noexcept; + + /// \brief Gets the type_info for the underlying stored type, or + /// \c typeid(void) if \ref has_value() returns \c false + /// + /// \return the typeid of the stored type + const std::type_info& type() const noexcept; + + //-------------------------------------------------------------------------- + // Private Static Members / Types + //-------------------------------------------------------------------------- + private: + + // Internal buffer size + alignment + static constexpr auto buffer_size = 4u * sizeof(void*); + static constexpr auto buffer_align = alignof(void*); + + // buffer (for internal storage) + using internal_buffer = typename aligned_storage::type; + + union storage + { + internal_buffer internal; + void* external; + }; + + //-------------------------------------------------------------------------- + + // trait to determine if internal storage is required + template + using requires_internal_storage = bool_constant< + (sizeof(T) <= buffer_size) && + ((buffer_align % alignof(T)) == 0) && + is_nothrow_move_constructible::value + >; + + //----------------------------------------------------------------------- + + template + struct internal_storage_handler; + + template + struct external_storage_handler; + + template + using storage_handler = conditional_t< + requires_internal_storage::value, + internal_storage_handler, + external_storage_handler + >; + + //----------------------------------------------------------------------- + + enum class operation + { + destroy, ///< Operation for calling the underlying's destructor + copy, ///< Operation for copying the underlying value + move, ///< Operation for moving the underlying value + value, ///< Operation for accessing the underlying value + type, ///< Operation for accessing the underlying type + }; + + //----------------------------------------------------------------------- + + using storage_handler_ptr = const void*(*)(operation, const storage*,const storage*); + + template + friend T* any_cast(any*) noexcept; + template + friend const T* any_cast(const any*) noexcept; + + //----------------------------------------------------------------------- + // Private Members + //----------------------------------------------------------------------- + private: + + storage m_storage; + storage_handler_ptr m_storage_handler; + }; + + //========================================================================= + // non-member functions : class : any + //========================================================================= + + //------------------------------------------------------------------------- + // utilities + //------------------------------------------------------------------------- + + /// \brief Swaps the contents of \p lhs and \p rhs + void swap(any& lhs, any& rhs) noexcept; + + //------------------------------------------------------------------------- + // casts + //------------------------------------------------------------------------- + + /// \{ + /// \brief Attempts to cast an any back to the underlying type T + /// + /// \throw bad_any_cast if \p any is not exactly of type \p T + /// \tparam T the type to cast to + /// \return the object + template + T any_cast(any& operand); + template + T any_cast(any&& operand); + template + T any_cast(const any& operand); + /// \} + + /// \{ + /// \brief Attempts to cast an any back to the underlying type T + /// + /// \tparam T the type to cast to + /// \return pointer to the object if successfull, nullptr otherwise + template + T* any_cast(any* operand) noexcept; + template + const T* any_cast(const any* operand) noexcept; + /// \} + +} // namespace bpstd + +//============================================================================= +// definitions : class : bad_any_cast +//============================================================================= + +inline +const char* bpstd::bad_any_cast::what() + const noexcept +{ + return "bad_any_cast"; +} + +//============================================================================= +// class : any::internal_storage_handler +//============================================================================= + +template +struct bpstd::any::internal_storage_handler +{ + template + static T* construct(storage& s, Args&&...args); + + template + static T* construct(storage& s, std::initializer_list il, Args&&...args); + + static void destroy(storage& s); + + static const void* handle(operation op, + const storage* self, + const storage* other); +}; + +//============================================================================= +// definition : class : any::internal_storage_handler +//============================================================================= + +template +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::any::internal_storage_handler + ::construct(storage& s, Args&&...args) +{ + return ::new(&s.internal) T(bpstd::forward(args)...); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::any::internal_storage_handler + ::construct(storage& s, std::initializer_list il, Args&&...args) +{ + return ::new(&s.internal) T(il, bpstd::forward(args)...); +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::any::internal_storage_handler + ::destroy(storage& s) +{ + auto* t = static_cast(static_cast(&s.internal)); + t->~T(); +} + +template +inline BPSTD_INLINE_VISIBILITY +const void* bpstd::any::internal_storage_handler + ::handle(operation op, + const storage* self, + const storage* other) +{ + switch (op) + { + case operation::destroy: + { + assert(self != nullptr); + BPSTD_UNUSED(other); + + destroy(const_cast(*self)); + break; + } + + case operation::copy: + { + assert(self != nullptr); + assert(other != nullptr); + + // Copy construct from the internal storage + const auto* p = reinterpret_cast(&other->internal); + construct( const_cast(*self), *p); + break; + } + + case operation::move: + { + assert(self != nullptr); + assert(other != nullptr); + + // Move construct from the internal storage. ' + const auto* p = reinterpret_cast(&other->internal); + construct(const_cast(*self), bpstd::move(*const_cast(p))); + break; + } + + case operation::value: + { + assert(self != nullptr); + BPSTD_UNUSED(other); + + // NOTE(bitwize): This seemingly arbitrary conversion is for proper + // type-safety/correctness. Otherwise, converting an aligned_storage_t* + // to void* and then to T* would violate strict-aliasing -- which + // would be undefined-behavior. Behavior is only well-defined for + // casts from void* to T* if the the void* originated from a T*. + const auto* p = reinterpret_cast(&self->internal); + return static_cast(p); + } + + case operation::type: + { + BPSTD_UNUSED(self); + BPSTD_UNUSED(other); + + return static_cast(&typeid(T)); + } + } + return nullptr; +} + +//============================================================================= +// class : any::external_storage_handler +//============================================================================= + +template +struct bpstd::any::external_storage_handler +{ + template + static T* construct(storage& s, Args&&...args); + + template + static T* construct(storage& s, std::initializer_list il, Args&&...args); + + static void destroy(storage& s); + + static const void* handle(operation op, + const storage* self, + const storage* other); +}; + + +//============================================================================= +// definition : class : any::external_storage_handler +//============================================================================= + +template +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::any::external_storage_handler + ::construct(storage& s, Args&&...args) +{ + s.external = new T(bpstd::forward(args)...); + return static_cast(s.external); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::any::external_storage_handler + ::construct(storage& s, std::initializer_list il, Args&&...args) +{ + s.external = new T(il, bpstd::forward(args)...); + return static_cast(s.external); +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::any::external_storage_handler + ::destroy(storage& s) +{ + delete static_cast(s.external); +} + +template +inline BPSTD_INLINE_VISIBILITY +const void* bpstd::any::external_storage_handler + ::handle( operation op, + const storage* self, + const storage* other ) +{ + switch (op) + { + case operation::destroy: + { + assert(self != nullptr); + BPSTD_UNUSED(other); + + destroy(const_cast(*self)); + break; + } + + case operation::copy: + { + assert(self != nullptr); + assert(other != nullptr); + + // Copy construct from the internal storage + construct( const_cast(*self), + *static_cast(other->external)); + break; + } + + case operation::move: + { + BPSTD_UNUSED(self != nullptr); + assert(other != nullptr); + + const auto p = static_cast(other->external); + // Move construct from the internal storage. ' + construct(const_cast(*self), bpstd::move(*const_cast(p))); + break; + } + + case operation::value: + { + assert(self != nullptr); + BPSTD_UNUSED(other); + + // self->external was already created as a T*; no need to cast like in + // internal. + return self->external; + } + + case operation::type: + { + BPSTD_UNUSED(self); + BPSTD_UNUSED(other); + + return &typeid(T); + } + } + return nullptr; +} + +//============================================================================= +// definitions : class : any +//============================================================================= + +//----------------------------------------------------------------------------- +// Constructors / Destructor / Assignment +//----------------------------------------------------------------------------- + +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any() + noexcept + : m_storage{}, + m_storage_handler{nullptr} +{ + +} + +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any(any&& other) + noexcept + : m_storage{}, + m_storage_handler{other.m_storage_handler} +{ + if (m_storage_handler != nullptr) { + m_storage_handler(operation::move, &m_storage, &other.m_storage); + } +} + +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any(const any& other) + : m_storage{}, + m_storage_handler{nullptr} +{ + + if (other.m_storage_handler != nullptr) { + // Set handler after constructing, in case of exception + const auto handler = other.m_storage_handler; + + handler(operation::copy, &m_storage, &other.m_storage); + m_storage_handler = handler; + } +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any(ValueType&& value) + : m_storage{}, + m_storage_handler{nullptr} +{ + // Set handler after constructing, in case of exception + using handler_type = storage_handler>; + + handler_type::construct(m_storage, bpstd::forward(value)); + m_storage_handler = &handler_type::handle; +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any(in_place_type_t, Args&&...args) + : m_storage{}, + m_storage_handler{nullptr} +{ + // Set handler after constructing, in case of exception + using handler_type = storage_handler>; + + handler_type::construct(m_storage, bpstd::forward(args)...); + m_storage_handler = &handler_type::handle; +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::any::any(in_place_type_t, + std::initializer_list il, + Args&&...args) + : m_storage{}, + m_storage_handler{nullptr} +{ + // Set handler after constructing, in case of exception + using handler_type = storage_handler>; + + handler_type::construct(m_storage, il, bpstd::forward(args)...); + m_storage_handler = &handler_type::handle; +} + +//----------------------------------------------------------------------------- + +inline BPSTD_INLINE_VISIBILITY +bpstd::any::~any() +{ + reset(); +} + +//----------------------------------------------------------------------------- + +inline BPSTD_INLINE_VISIBILITY +bpstd::any& bpstd::any::operator=(any&& other) + noexcept +{ + reset(); + + if (other.m_storage_handler != nullptr) { + m_storage_handler = other.m_storage_handler; + m_storage_handler(operation::move, &m_storage, &other.m_storage); + } + + return (*this); +} + +inline BPSTD_INLINE_VISIBILITY +bpstd::any& bpstd::any::operator=(const any& other) +{ + reset(); + + if (other.m_storage_handler != nullptr) { + // Set handler after constructing, in case of exception + const auto handler = other.m_storage_handler; + + handler(operation::copy, &m_storage, &other.m_storage); + m_storage_handler = handler; + } + + return (*this); +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::any& bpstd::any::operator=(ValueType&& value) +{ + using handler_type = storage_handler>; + + reset(); + + handler_type::construct(m_storage, bpstd::forward(value)); + m_storage_handler = &handler_type::handle; + + return (*this); +} + +//----------------------------------------------------------------------------- +// Modifiers +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::decay_t& + bpstd::any::emplace(Args&&...args) +{ + using handler_type = storage_handler>; + + reset(); + + auto& result = *handler_type::construct(m_storage, + bpstd::forward(args)...); + m_storage_handler = &handler_type::handle; + + return result; +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::decay_t& + bpstd::any::emplace(std::initializer_list il, + Args&&...args) +{ + using handler_type = storage_handler>; + + reset(); + + auto& result = *handler_type::construct(m_storage, + il, + bpstd::forward(args)...); + m_storage_handler = &handler_type::handle; + + return result; +} + +inline BPSTD_INLINE_VISIBILITY +void bpstd::any::reset() + noexcept +{ + if (m_storage_handler != nullptr) { + m_storage_handler(operation::destroy, &m_storage, nullptr); + m_storage_handler = nullptr; + } +} + +inline BPSTD_INLINE_VISIBILITY +void bpstd::any::swap(any& other) + noexcept +{ + using std::swap; + + if (m_storage_handler != nullptr && other.m_storage_handler != nullptr) + { + auto tmp = any{}; + + // tmp := self + tmp.m_storage_handler = m_storage_handler; + m_storage_handler(operation::move, &tmp.m_storage, &m_storage); + m_storage_handler(operation::destroy, &m_storage, nullptr); + + // self := other + m_storage_handler = other.m_storage_handler; + m_storage_handler(operation::move, &m_storage, &other.m_storage); + m_storage_handler(operation::destroy, &other.m_storage, nullptr); + + // other := tmp + other.m_storage_handler = tmp.m_storage_handler; + other.m_storage_handler(operation::move, &other.m_storage, &tmp.m_storage); + } + else if (other.m_storage_handler != nullptr) + { + swap(m_storage_handler, other.m_storage_handler); + + // self := other + m_storage_handler(operation::move, &m_storage, &other.m_storage); + m_storage_handler(operation::destroy, &other.m_storage, nullptr); + } + else if (m_storage_handler != nullptr) + { + swap(m_storage_handler, other.m_storage_handler); + + // other := self + other.m_storage_handler(operation::move, &other.m_storage, &m_storage); + other.m_storage_handler(operation::destroy, &m_storage, nullptr); + } +} + +//----------------------------------------------------------------------------- +// Observers +//----------------------------------------------------------------------------- + +inline BPSTD_INLINE_VISIBILITY +bool bpstd::any::has_value() + const noexcept +{ + return m_storage_handler != nullptr; +} + +inline BPSTD_INLINE_VISIBILITY +const std::type_info& bpstd::any::type() + const noexcept +{ + if (has_value()) { + auto* p = m_storage_handler(operation::type, nullptr, nullptr); + return (*static_cast(p)); + } + return typeid(void); +} + +//============================================================================= +// definition : non-member functions : class : any +//============================================================================= + +//----------------------------------------------------------------------------- +// utilities +//----------------------------------------------------------------------------- + +inline BPSTD_INLINE_VISIBILITY +void bpstd::swap(any& lhs, any& rhs) + noexcept +{ + lhs.swap(rhs); +} + +//----------------------------------------------------------------------------- +// casts +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +T bpstd::any_cast(any& operand) +{ + using underlying_type = remove_cvref_t; + + static_assert( + is_constructible::value, + "A program is ill-formed if T is not constructible from U&" + ); + + auto* p = any_cast(&operand); + if (p == nullptr) { + throw bad_any_cast{}; + } + return static_cast(*p); +} + +template +inline BPSTD_INLINE_VISIBILITY +T bpstd::any_cast(any&& operand) +{ + using underlying_type = remove_cvref_t; + + static_assert( + is_constructible::value, + "A program is ill-formed if T is not constructible from U" + ); + + auto* p = any_cast(&operand); + if (p == nullptr) { + throw bad_any_cast{}; + } + return static_cast(bpstd::move(*p)); +} + +template +inline BPSTD_INLINE_VISIBILITY +T bpstd::any_cast(const any& operand) +{ + using underlying_type = remove_cvref_t; + + static_assert( + is_constructible::value, + "A program is ill-formed if T is not constructible from const U&" + ); + + const auto* p = any_cast(&operand); + if (p == nullptr) { + throw bad_any_cast{}; + } + return static_cast(*p); +} + +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::any_cast(any* operand) + noexcept +{ + if (!operand) { + return nullptr; + } + if (operand->type() != typeid(T)) { + return nullptr; + } + + auto p = operand->m_storage_handler(any::operation::value, + &operand->m_storage, + nullptr); + return const_cast(static_cast(p)); +} + +template +inline BPSTD_INLINE_VISIBILITY +const T* bpstd::any_cast(const any* operand) + noexcept +{ + if (!operand) { + return nullptr; + } + if (operand->type() != typeid(T)) { + return nullptr; + } + + auto* p = operand->m_storage_handler(any::operation::value, + &operand->m_storage, + nullptr); + return static_cast(p); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_ANY_HPP */ diff --git a/src/libs/vmisc/bpstd/chrono.hpp b/src/libs/vmisc/bpstd/chrono.hpp new file mode 100644 index 000000000..e390eb339 --- /dev/null +++ b/src/libs/vmisc/bpstd/chrono.hpp @@ -0,0 +1,438 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file chrono.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_CHRONO_HPP +#define BPSTD_CHRONO_HPP + +#include "detail/config.hpp" + +#include // std::chrono::duration, std::chrono::system_clock, etc +#include // std::int32_t + +#if __cplusplus < 201402L +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) +#include "../vmisc/diagnostic.h" +#endif // QT_VERSION < QT_VERSION_CHECK(5, 5, 0) +#endif + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace chrono { + + template > + using duration = std::chrono::duration; + + template + using time_point = std::chrono::time_point; + + using nanoseconds = std::chrono::nanoseconds; + using microseconds = std::chrono::microseconds; + using milliseconds = std::chrono::milliseconds; + using seconds = std::chrono::seconds; + using minutes = std::chrono::minutes; + using hours = std::chrono::hours; + using days = std::chrono::duration>; + using weeks = std::chrono::duration>; + using months = std::chrono::duration>; + using years = std::chrono::duration>; + + using steady_clock = std::chrono::steady_clock; + using system_clock = std::chrono::system_clock; + + template + using sys_time = time_point; + using sys_seconds = sys_time; + using sys_days = sys_time; + + + } // namespace chrono + + //============================================================================ + // non-member functions + //============================================================================ + + //---------------------------------------------------------------------------- + // Literals + //---------------------------------------------------------------------------- + + inline namespace literals { + inline namespace chrono_literals { + + constexpr auto operator""_h(unsigned long long x) -> std::chrono::hours; + constexpr auto operator""_h(long double x) -> std::chrono::duration>; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""h(unsigned long long x) -> std::chrono::hours; + constexpr auto operator""h(long double x) -> std::chrono::duration>; + + QT_WARNING_POP +#endif + + constexpr auto operator""_min(unsigned long long x) -> chrono::minutes; + constexpr auto operator""_min(long double x) -> chrono::duration>; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""min(unsigned long long x) -> chrono::minutes; + constexpr auto operator""min(long double x) -> chrono::duration>; + + QT_WARNING_POP +#endif + + constexpr auto operator""_s(unsigned long long x) -> chrono::seconds; + constexpr auto operator""_s(long double x) -> chrono::duration; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""s(unsigned long long x) -> chrono::seconds; + constexpr auto operator""s(long double x) -> chrono::duration; + + QT_WARNING_POP +#endif + + constexpr auto operator""_ms(unsigned long long x) -> chrono::milliseconds; + constexpr auto operator""_ms(long double x) -> chrono::duration; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""ms(unsigned long long x) -> chrono::milliseconds; + constexpr auto operator""ms(long double x) -> chrono::duration; + + QT_WARNING_POP +#endif + + constexpr auto operator""_us(unsigned long long x) -> chrono::microseconds; + constexpr auto operator""_us(long double x) -> chrono::duration; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""us(unsigned long long x) -> chrono::microseconds; + constexpr auto operator""us(long double x) -> chrono::duration; + + QT_WARNING_POP +#endif + + constexpr auto operator""_ns(unsigned long long x) -> chrono::nanoseconds; + constexpr auto operator""_ns(long double x) -> chrono::duration; + +#if __cplusplus < 201402L + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") + QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + + // available only since C++14 + constexpr auto operator""ns(unsigned long long x) -> chrono::nanoseconds; + constexpr auto operator""ns(long double x) -> chrono::duration; + + QT_WARNING_POP +#endif + + } // namespace chrono_literals + } // namespace literals +} // namespace bpstd + +inline BPSTD_INLINE_VISIBILITY constexpr +auto + bpstd::literals::chrono_literals::operator""_h(unsigned long long x) -> std::chrono::hours +{ + return chrono::hours{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""h(unsigned long long x) -> std::chrono::hours +{ + return chrono::hours{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_h(long double x) -> std::chrono::duration> +{ + return chrono::duration>{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""h(long double x) -> std::chrono::duration> +{ + return chrono::duration>{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_min(unsigned long long x) -> bpstd::chrono::minutes +{ + return chrono::minutes{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""min(unsigned long long x) -> bpstd::chrono::minutes +{ + return chrono::minutes{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_min(long double x) -> bpstd::chrono::duration> +{ + return chrono::duration>{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""min(long double x) -> bpstd::chrono::duration> +{ + return chrono::duration>{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_s(unsigned long long x) -> bpstd::chrono::seconds +{ + return chrono::seconds{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""s(unsigned long long x) -> bpstd::chrono::seconds +{ + return chrono::seconds{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_s(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""s(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_ms(unsigned long long x) -> bpstd::chrono::milliseconds +{ + return chrono::milliseconds{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""ms(unsigned long long x) -> bpstd::chrono::milliseconds +{ + return chrono::milliseconds{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_ms(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""ms(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator ""_us(unsigned long long x) -> bpstd::chrono::microseconds +{ + return chrono::microseconds{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator ""us(unsigned long long x) -> bpstd::chrono::microseconds +{ + return chrono::microseconds{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_us(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""us(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_ns(unsigned long long x) -> bpstd::chrono::nanoseconds +{ + return chrono::nanoseconds{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""ns(unsigned long long x) -> bpstd::chrono::nanoseconds +{ + return chrono::nanoseconds{x}; +} + +QT_WARNING_POP +#endif + +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""_ns(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +#if __cplusplus < 201402L +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wuser-defined-literals") +QT_WARNING_DISABLE_GCC("-Wliteral-suffix") + +// available only since C++14 +inline BPSTD_INLINE_VISIBILITY constexpr +auto bpstd::literals::chrono_literals::operator""ns(long double x) -> bpstd::chrono::duration +{ + return chrono::duration{x}; +} + +QT_WARNING_POP +#endif + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_CHRONO_HPP */ diff --git a/src/libs/vmisc/bpstd/complex.hpp b/src/libs/vmisc/bpstd/complex.hpp new file mode 100644 index 000000000..271579b30 --- /dev/null +++ b/src/libs/vmisc/bpstd/complex.hpp @@ -0,0 +1,122 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file complex.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_COMPLEX_HPP +#define BPSTD_COMPLEX_HPP + +#include "detail/config.hpp" + +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // class : complex + //============================================================================ + + template + using complex = std::complex; + + //============================================================================ + // literals : class : complex + //============================================================================ + + inline namespace literals { + inline namespace complex_literals { + + constexpr complex operator""_il(long double i) noexcept; + constexpr complex operator""_il(unsigned long long i) noexcept; + + constexpr complex operator""_i(long double i) noexcept; + constexpr complex operator""_i(unsigned long long i) noexcept; + + constexpr complex operator""_if(long double i) noexcept; + constexpr complex operator""_if(unsigned long long i) noexcept; + + } // namespace complex_literals + } // namespace literals +} // namespace bpstd + +//============================================================================== +// literals : class : complex +//============================================================================== + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_il(long double i) + noexcept +{ + return complex{0, i}; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_il(unsigned long long i) + noexcept +{ + return complex{0, static_cast(i)}; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_i(long double i) + noexcept +{ + return complex{0, static_cast(i)}; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_i(unsigned long long i) + noexcept +{ + return complex{0, static_cast(i)}; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_if(long double i) + noexcept +{ + return complex{0, static_cast(i)}; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::complex + bpstd::literals::complex_literals::operator""_if(unsigned long long i) + noexcept +{ + return complex{0, static_cast(i)}; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_COMPLEX_HPP */ diff --git a/src/libs/vmisc/bpstd/cstddef.hpp b/src/libs/vmisc/bpstd/cstddef.hpp new file mode 100644 index 000000000..4993e8cbd --- /dev/null +++ b/src/libs/vmisc/bpstd/cstddef.hpp @@ -0,0 +1,258 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file cstddef.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_CSTDDEF_HPP +#define BPSTD_CSTDDEF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "type_traits.hpp" + +#include // std::is_integral +#include // __cpp_lib_byte, and to proxy API + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +// The below implementation is based on GSL's implementation of 'gsl::byte' + +// VS2017 15.8 added support for the __cpp_lib_byte definition +// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires +#if defined(_MSC_VER) + +// Turn MSVC /analyze rules that generate too much noise. +# pragma warning(push) +# pragma warning(disable : 26493) // don't use c-style cast + +# if !defined(BPSTD_USE_STD_BYTE) +// this tests if we are under MSVC and the standard lib has std::byte and it is +// enabled +# if defined(_HAS_STD_BYTE) && _HAS_STD_BYTE +# define BPSTD_USE_STD_BYTE 1 +# elif defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603 +# define BPSTD_USE_STD_BYTE 1 +# else +# define BPSTD_USE_STD_BYTE 0 +# endif +# endif // BPSTD_USE_STD_BYTE +#endif // _MSC_VER + +#if !defined(BPSTD_USE_STD_BYTE) + +// this tests if we are under GCC or Clang with enough -std:c++1z power to get us std::byte +// also check if libc++ version is sufficient (> 5.0) or libstc++ actually contains std::byte +# if defined(__cplusplus) && (__cplusplus >= 201703L) && \ + (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ + defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) +# define BPSTD_USE_STD_BYTE 1 +# else +# define BPSTD_USE_STD_BYTE 0 +# endif +#endif // BPSTD_USE_STD_BYTE + +namespace bpstd { + +#if BPSTD_USE_STD_BYTE + using std::byte; +#else + enum class BPSTD_MAY_ALIAS byte : unsigned char {}; + + //============================================================================ + // non-member functions : enum lass : byte + //============================================================================ + + //---------------------------------------------------------------------------- + // Bitwise operators + //---------------------------------------------------------------------------- + + template ::value>> + constexpr byte operator<<(byte b, Integer shift) noexcept; + template ::value>> + constexpr byte operator>>(byte b, Integer shift) noexcept; + + constexpr byte operator|(byte lhs, byte rhs) noexcept; + constexpr byte operator&(byte lhs, byte rhs) noexcept; + constexpr byte operator^(byte lhs, byte rhs) noexcept; + constexpr byte operator~(byte b) noexcept; + + //---------------------------------------------------------------------------- + // Compound Bitwise Operators + //---------------------------------------------------------------------------- + + template ::value>> + BPSTD_CPP14_CONSTEXPR byte& operator<<=(byte& b, Integer shift) noexcept; + template ::value>> + BPSTD_CPP14_CONSTEXPR byte& operator>>=(byte& b, Integer shift) noexcept; + BPSTD_CPP14_CONSTEXPR byte& operator|=(byte& lhs, byte rhs) noexcept; + BPSTD_CPP14_CONSTEXPR byte& operator&=(byte& lhs, byte rhs) noexcept; + + BPSTD_CPP14_CONSTEXPR byte& operator^=(byte& lhs, byte rhs) noexcept; + +#endif + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + template ::value>> + constexpr Integer to_integer(byte b) noexcept; + +} // namespace bpstd + +//============================================================================== +// definitions : non-member functions : enum class : byte +//============================================================================== + +#if !BPSTD_USE_STD_BYTE + +//------------------------------------------------------------------------------ +// Bitwise Operators +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator<<(byte b, Integer shift) + noexcept +{ + return static_cast(static_cast(b) << shift); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator>>(byte b, Integer shift) + noexcept +{ + return static_cast(static_cast(b) >> shift); +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator|(byte lhs, byte rhs) + noexcept +{ + return static_cast( + static_cast(lhs) | static_cast(rhs) + ); +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator&(byte lhs, byte rhs) + noexcept +{ + return static_cast( + static_cast(lhs) & static_cast(rhs) + ); +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator^(byte lhs, byte rhs) + noexcept +{ + return static_cast( + static_cast(lhs) ^ static_cast(rhs) + ); +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::byte bpstd::operator~(byte b) + noexcept +{ + return static_cast(~static_cast(b)); +} + +//------------------------------------------------------------------------------ +// Compound Bitwise Operators +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::byte& bpstd::operator<<=(byte& b, Integer shift) + noexcept +{ + return b = static_cast(static_cast(b) << shift); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::byte& bpstd::operator>>=(byte& b, Integer shift) + noexcept +{ + return b = static_cast(static_cast(b) >> shift); +} + +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::byte& bpstd::operator|=(byte& lhs, byte rhs) + noexcept +{ + return lhs = static_cast( + static_cast(lhs) | static_cast(rhs) + ); +} + +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::byte& bpstd::operator&=(byte& lhs, byte rhs) + noexcept +{ + return lhs = static_cast( + static_cast(lhs) & static_cast(rhs) + ); +} + +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::byte& bpstd::operator^=(byte& lhs, byte rhs) + noexcept +{ + return lhs = static_cast( + static_cast(lhs) ^ static_cast(rhs) + ); +} + +#endif // BPSTD_USE_STD_BYTE + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +Integer bpstd::to_integer(byte b) + noexcept +{ + return static_cast(b); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_CSTDDEF_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/config.hpp b/src/libs/vmisc/bpstd/detail/config.hpp new file mode 100644 index 000000000..751e4dba8 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/config.hpp @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file config.hpp +/// +/// \brief This header provides configuration data for the bpstd library +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_CONFIG_HPP +#define BPSTD_DETAIL_CONFIG_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if !defined(__cplusplus) +# error This library requires a C++ compiler +#endif + +// _MSC_VER check is due to MSVC not defining __cplusplus to be 201103L +#if !defined(_MSC_VER) && __cplusplus < 201103L +# error This library must be compiled with C++11 support +#endif + +#if defined(__cplusplus) && __cplusplus >= 201402L +# define BPSTD_CPP14_CONSTEXPR constexpr +# define BPSTD_HAS_TEMPLATE_VARIABLES 1 +#else +# define BPSTD_CPP14_CONSTEXPR +# define BPSTD_HAS_TEMPLATE_VARIABLES 0 +#endif + +#if defined(__cplusplus) && __cplusplus >= 201703L +# define BPSTD_CPP17_CONSTEXPR constexpr +# define BPSTD_CPP17_INLINE inline +# define BPSTD_HAS_INLINE_VARIABLES 1 +#else +# define BPSTD_CPP17_CONSTEXPR +# define BPSTD_CPP17_INLINE +# define BPSTD_HAS_INLINE_VARIABLES 0 +#endif + +#define BPSTD_UNUSED(x) static_cast(x) + +// Use __may_alias__ attribute on gcc and clang +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 5) +# define BPSTD_MAY_ALIAS __attribute__((__may_alias__)) +#else // defined(__clang__) || defined __GNUC__ +# define BPSTD_MAY_ALIAS +#endif // defined __clang__ || defined __GNUC__ + +#if !defined(BPSTD_INLINE_VISIBILITY) +// When using 'clang-cl', don't forceinline -- since it results in code generation +// failures in 'variant' +# if defined(__clang__) && defined(_MSC_VER) +# define BPSTD_INLINE_VISIBILITY __attribute__((visibility("hidden"), no_instrument_function)) +# elif defined(__clang__) || defined(__GNUC__) +# define BPSTD_INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline, no_instrument_function)) +# elif defined(_MSC_VER) +# define BPSTD_INLINE_VISIBILITY __forceinline +# else +# define BPSTD_INLINE_VISIBILITY +# endif +#endif // !defined(BPSTD_INLINE_VISIBILITY) + +#if defined(_MSC_VER) +# define BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE \ + __pragma(warning(push)) \ + __pragma(warning(disable:4714)) \ + __pragma(warning(disable:4100)) +#else +# define BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE +#endif + +#if defined(_MSC_VER) +# define BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE \ + __pragma(warning(pop)) +#else +# define BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE +#endif + +#endif /* BPSTD_DETAIL_CONFIG_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/enable_overload.hpp b/src/libs/vmisc/bpstd/detail/enable_overload.hpp new file mode 100644 index 000000000..cfa30a3cc --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/enable_overload.hpp @@ -0,0 +1,73 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file enable_overload.hpp +/// +/// \brief This internal header provides the definition of a SFINAE utility +/// for conditionally enabling overloads +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_ENABLE_OVERLOAD_HPP +#define BPSTD_DETAIL_ENABLE_OVERLOAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +namespace bpstd { + namespace detail { + + /// \brief Similar to enable_if, but doesn't sfinae-away a type; instead + /// produces an uninstantiable unique type when true + /// + /// This is used to selectively disable constructors, since sfinae doesn't + /// work for copy/move constructors + template + struct enable_overload_if + { + using type = T; + }; + + template + struct enable_overload_if + { + class type{ type() = delete; ~type() = delete; }; + }; + + template + using enable_overload_if_t = typename enable_overload_if::type; + + /// \brief Inverse of enable_overload_if + template + using disable_overload_if = enable_overload_if; + + /// \brief Convenience alias to retrieve the ::type member of + /// disable_overload_if + template + using disable_overload_if_t = typename disable_overload_if::type; + + } // namespace detail +} // namespace bpstd + +#endif /* BPSTD_DETAIL_ENABLE_OVERLOAD_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/invoke.hpp b/src/libs/vmisc/bpstd/detail/invoke.hpp new file mode 100644 index 000000000..4e02c6638 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/invoke.hpp @@ -0,0 +1,188 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file invoke.hpp +/// +/// \brief This internal header provides the definition of the INVOKE overload +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_INVOKE_HPP +#define BPSTD_DETAIL_INVOKE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" // BPSTD_INLINE_VISIBILITY +#include "move.hpp" // forward +#include // std::true_type, std::false_type, etc +#include // std::reference_wrapper + +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + template + struct is_reference_wrapper : std::false_type {}; + + template + struct is_reference_wrapper> : std::true_type {}; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) + noexcept(noexcept((::bpstd::forward(ref).*pmf)(::bpstd::forward(args)...))) + -> typename std::enable_if::value && + std::is_base_of::type>::value, + decltype((::bpstd::forward(ref).*pmf)(::bpstd::forward(args)...))>::type + { + return (bpstd::forward(ref).*pmf)(bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args) + noexcept(noexcept((ref.get().*pmf)(std::forward(args)...))) + -> typename std::enable_if::value && + is_reference_wrapper::type>::value, + decltype((ref.get().*pmf)(::bpstd::forward(args)...))>::type + { + return (ref.get().*pmf)(bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args) + noexcept(noexcept(((*std::forward(ptr)).*pmf)(std::forward(args)...))) + -> typename std::enable_if::value && + !is_reference_wrapper::type>::value && + !std::is_base_of::type>::value, + decltype(((*::bpstd::forward(ptr)).*pmf)(::bpstd::forward(args)...))>::type + { + return ((*bpstd::forward(ptr)).*pmf)(bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmd, Derived&& ref) + noexcept(noexcept(std::forward(ref).*pmd)) + -> typename std::enable_if::value && + std::is_base_of::type>::value, + decltype(::bpstd::forward(ref).*pmd)>::type + { + return bpstd::forward(ref).*pmd; + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmd, RefWrap&& ref) + noexcept(noexcept(ref.get().*pmd)) + -> typename std::enable_if::value && + is_reference_wrapper::type>::value, + decltype(ref.get().*pmd)>::type + { + return ref.get().*pmd; + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(T Base::*pmd, Pointer&& ptr) + noexcept(noexcept((*std::forward(ptr)).*pmd)) + -> typename std::enable_if::value && + !is_reference_wrapper::type>::value && + !std::is_base_of::type>::value, + decltype((*::bpstd::forward(ptr)).*pmd)>::type + { + return (*bpstd::forward(ptr)).*pmd; + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto INVOKE(F&& f, Args&&... args) + noexcept(noexcept(std::forward(f)(std::forward(args)...))) + -> typename std::enable_if::type>::value, + decltype(::bpstd::forward(f)(::bpstd::forward(args)...))>::type + { + return bpstd::forward(f)(bpstd::forward(args)...); + } + + //========================================================================== + // is_nothrow_invocable + //========================================================================== + + template + struct is_nothrow_invocable + { + template + static auto test( Fn2&&, Args2&&... ) + -> decltype(INVOKE(std::declval(), std::declval()...), + std::integral_constant(), std::declval()...))>{}); + + static auto test(...) + -> std::false_type; + + using type = decltype(test(std::declval(), std::declval()...)); + static constexpr bool value = type::value; + }; + + //========================================================================== + // is_invocable + //========================================================================== + + template + struct is_invocable + { + template + static auto test( Fn2&&, Args2&&... ) + -> decltype(INVOKE(std::declval(), std::declval()...), std::true_type{}); + + static auto test(...) + -> std::false_type; + + using type = decltype(test(std::declval(), std::declval()...)); + static constexpr bool value = type::value; + }; + + // Used to SFINAE away non-invocable types + template + struct invoke_result_impl{}; + + template + struct invoke_result_impl{ + using type = decltype(INVOKE(std::declval(), std::declval()...)); + }; + + template + struct invoke_result + : invoke_result_impl::value, Fn, Args...>{}; + + } // namespace detail +} // namespace bpstd + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_INVOKE_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/move.hpp b/src/libs/vmisc/bpstd/detail/move.hpp new file mode 100644 index 000000000..471e665bf --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/move.hpp @@ -0,0 +1,115 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file move.hpp +/// +/// \brief This internal header provides the definition of the move and forward +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_MOVE_HPP +#define BPSTD_DETAIL_MOVE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" + +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + /// \{ + /// \brief Forwards a reference \p t + /// + /// \tparam T the type to forward + /// \param t the reference + /// \return the forwarded reference + template + constexpr T&& forward(typename std::remove_reference::type& t) noexcept; + template + constexpr T&& forward(typename std::remove_reference::type&& t) noexcept; + /// \} + + /// \brief Casts \p x to an rvalue + /// + /// \param x the parameter to move + /// \return rvalue reference to \p x + template + constexpr T&& move(T& x) noexcept; + + /// \brief Casts \p x to an rvalue + /// + /// \param x the parameter to move + /// \return rvalue reference to \p x + template + constexpr typename std::remove_reference::type&& move(T&& x) noexcept; + +} // namespace bpstd + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T&& bpstd::forward(typename std::remove_reference::type& t) + noexcept +{ + return static_cast(t); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T&& bpstd::forward(typename std::remove_reference::type&& t) + noexcept +{ + return static_cast(t); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T&& bpstd::move(T& x) + noexcept +{ + return static_cast(x); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename std::remove_reference::type&& bpstd::move(T&& x) + noexcept +{ + return static_cast(x); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_MOVE_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/nth_type.hpp b/src/libs/vmisc/bpstd/detail/nth_type.hpp new file mode 100644 index 000000000..2d3edb925 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/nth_type.hpp @@ -0,0 +1,64 @@ +/***************************************************************************** + * \file nth_type.hpp + * + * \brief This internal header provides the definition of the INVOKE overload + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_NTH_TYPE_HPP +#define BPSTD_DETAIL_NTH_TYPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include // std::size_t + +namespace bpstd { + namespace detail { + + /// \brief Gets the nth type from a variadic pack of arguments + /// + /// \tparam N the argument to retrieve + /// \tparam Args the arguments to extract from + template + struct nth_type; + + template + struct nth_type : nth_type{}; + + template + struct nth_type<0,Arg0,Args...> + { + using type = Arg0; + }; + + template + using nth_type_t = typename nth_type::type; + + } // namespace detail +} // namespace bpstd + +#endif /* BPSTD_DETAIL_NTH_TYPE_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/proxy_iterator.hpp b/src/libs/vmisc/bpstd/detail/proxy_iterator.hpp new file mode 100644 index 000000000..e9a043e05 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/proxy_iterator.hpp @@ -0,0 +1,450 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file proxy_iterator.hpp +/// +/// \brief This internal header provides the definition of an iterator wrapper +/// type used for uniqueness +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_PROXY_ITERATOR_HPP +#define BPSTD_DETAIL_PROXY_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "config.hpp" +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + //========================================================================== + // class : proxy_iterator + //========================================================================== + + /////////////////////////////////////////////////////////////////////////// + /// \brief A thin wrapper around a different iterator type to add + /// uniqueness + /// + /// This makes any regular Iterator type such as a pointer to be unique, + /// and incomparable to other pointers. + /// + /// \tparam Iterator the pointer type to wrap + /// \tparam U a type to make this iterator unique, and not comparable with + /// other proxy_iterators + /////////////////////////////////////////////////////////////////////////// + template + class proxy_iterator +#if __cplusplus < 201703L + : public std::iterator< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + > +#endif + { +#if __cplusplus < 201703L + using base_type = std::iterator< + typename std::iterator_traits::iterator_category, + typename std::iterator_traits::value_type, + typename std::iterator_traits::difference_type, + typename std::iterator_traits::pointer, + typename std::iterator_traits::reference + >; +#endif + //------------------------------------------------------------------------ + // Public Member Types + //------------------------------------------------------------------------ + public: + +#if __cplusplus >= 201703L + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = typename std::iterator_traits::value_type; + using pointer = typename std::iterator_traits::pointer; + using reference = typename std::iterator_traits::reference; + using difference_type = typename std::iterator_traits::difference_type; +#else + using iterator_category = typename base_type::iterator_category; + using value_type = typename base_type::value_type; + using pointer = typename base_type::pointer; + using reference = typename base_type::reference; + using difference_type = typename base_type::difference_type; +#endif + + //------------------------------------------------------------------------ + // Constructor + //------------------------------------------------------------------------ + public: + + /// \brief Default constructs this proxy_iterator by default-constructing + /// the underlying iterator + constexpr proxy_iterator() = default; + + /// \brief Constructs a proxy_iterator from a given pointer + /// + /// \param it the iterator to construct this proxy_iterator + constexpr explicit proxy_iterator(const Iterator& it) noexcept; + + /// \brief Convert-constructs a proxy_iterator from a proxy iterator with + /// the same tag + /// + /// \param it the iterator + template + constexpr proxy_iterator(const proxy_iterator& it) noexcept; + + /// \brief Copy-constructs a proxy_iterator + /// + /// \param other the iterator to copy + constexpr proxy_iterator(const proxy_iterator& other) noexcept = default; + + /// \brief Move-constructs a proxy_iterator + /// + /// \param other the iterator to move + constexpr proxy_iterator(proxy_iterator&& other) noexcept = default; + + /// \brief Copy-assigns a proxy_iterator + /// + /// \param it the iterator to copy + template + proxy_iterator& operator=(const proxy_iterator& it) noexcept; + + /// \brief Copy-assigns a proxy_iterator + /// + /// \param other the iterator to copy + proxy_iterator& operator=(const proxy_iterator& other) noexcept = default; + + /// \brief Move-assigns a proxy_iterator + /// + /// \param other the iterator to move + proxy_iterator& operator=(proxy_iterator&& other) noexcept = default; + + //------------------------------------------------------------------------ + // Iteration + //------------------------------------------------------------------------ + public: + + BPSTD_CPP14_CONSTEXPR proxy_iterator& operator++() noexcept; + BPSTD_CPP14_CONSTEXPR proxy_iterator operator++(int) noexcept; + BPSTD_CPP14_CONSTEXPR proxy_iterator& operator--() noexcept; + BPSTD_CPP14_CONSTEXPR proxy_iterator operator--(int) noexcept; + + //------------------------------------------------------------------------ + // Random Access + //------------------------------------------------------------------------ + public: + + BPSTD_CPP14_CONSTEXPR proxy_iterator& operator+=(difference_type n) noexcept; + BPSTD_CPP14_CONSTEXPR proxy_iterator& operator-=(difference_type n) noexcept; + + constexpr difference_type operator-(const proxy_iterator& rhs) const noexcept; + constexpr reference operator[](difference_type index) const noexcept; + + //------------------------------------------------------------------------ + // Observers + //------------------------------------------------------------------------ + public: + + constexpr pointer operator->() const noexcept; + constexpr reference operator*() const noexcept; + + //------------------------------------------------------------------------ + // Comparison + //------------------------------------------------------------------------ + public: + + constexpr bool operator==(const proxy_iterator& rhs) const noexcept; + constexpr bool operator!=(const proxy_iterator& rhs) const noexcept; + constexpr bool operator< (const proxy_iterator& rhs) const noexcept; + constexpr bool operator<=(const proxy_iterator& rhs) const noexcept; + constexpr bool operator> (const proxy_iterator& rhs) const noexcept; + constexpr bool operator>=(const proxy_iterator& rhs) const noexcept; + + //------------------------------------------------------------------------ + // Private Members + //------------------------------------------------------------------------ + private: + + Iterator m_iter; ///< The iterator used for iteration + + template friend class proxy_iterator; + }; + + //========================================================================== + // non-member functions : class : proxy_iterator + //========================================================================== + + //-------------------------------------------------------------------------- + // Random Access + //-------------------------------------------------------------------------- + + template + BPSTD_CPP14_CONSTEXPR proxy_iterator + operator+(const proxy_iterator& lhs, + typename proxy_iterator::difference_type rhs) noexcept; + + template + BPSTD_CPP14_CONSTEXPR proxy_iterator + operator+(typename proxy_iterator::difference_type lhs, + const proxy_iterator& rhs) noexcept; + + template + BPSTD_CPP14_CONSTEXPR proxy_iterator + operator-(const proxy_iterator& lhs, + typename proxy_iterator::difference_type rhs) noexcept; + + } // namespace detail +} // namespace bpstd + +//============================================================================== +// definitions : class : proxy_iterator +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors / Assignment +//------------------------------------------------------------------------------ + +template +inline constexpr bpstd::detail::proxy_iterator:: + proxy_iterator(const Iterator& it) + noexcept + : m_iter{it} +{ + +} + +template +template +inline constexpr bpstd::detail::proxy_iterator + ::proxy_iterator(const proxy_iterator& it) + noexcept + : m_iter{it.m_iter} +{ + +} + +template +template +inline bpstd::detail::proxy_iterator& + bpstd::detail::proxy_iterator::operator=(const proxy_iterator& it) + noexcept +{ + m_iter = it.m_iter; + + return (*this); +} + +//------------------------------------------------------------------------------ +// Iteration +//------------------------------------------------------------------------------ + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator& + bpstd::detail::proxy_iterator::operator++() + noexcept +{ + ++m_iter; + return (*this); +} + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator + bpstd::detail::proxy_iterator::operator++(int) + noexcept +{ + return proxy_iterator{m_iter++}; +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator& + bpstd::detail::proxy_iterator::operator--() + noexcept +{ + --m_iter; + return (*this); +} + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator + bpstd::detail::proxy_iterator::operator--(int) + noexcept +{ + return proxy_iterator{m_iter--}; +} + +//------------------------------------------------------------------------------ +// Random Access +//------------------------------------------------------------------------------ + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator& + bpstd::detail::proxy_iterator::operator+=(difference_type n) + noexcept +{ + m_iter += n; + return (*this); +} + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator& + bpstd::detail::proxy_iterator::operator-=(difference_type n) + noexcept +{ + m_iter -= n; + return (*this); +} + +template +inline constexpr typename bpstd::detail::proxy_iterator::difference_type + bpstd::detail::proxy_iterator::operator-(const proxy_iterator& rhs) + const noexcept +{ + return m_iter - rhs.m_iter; +} + +template +inline constexpr typename bpstd::detail::proxy_iterator::reference + bpstd::detail::proxy_iterator::operator[](difference_type index) + const noexcept +{ + return m_iter[index]; +} + +//------------------------------------------------------------------------------ +// Observers +//------------------------------------------------------------------------------ + +template +inline constexpr typename bpstd::detail::proxy_iterator::pointer + bpstd::detail::proxy_iterator::operator->() + const noexcept +{ + return m_iter; +} + +template +inline constexpr typename bpstd::detail::proxy_iterator::reference + bpstd::detail::proxy_iterator::operator*() + const noexcept +{ + return *m_iter; +} + +//------------------------------------------------------------------------------ +// Comparisons +//------------------------------------------------------------------------------ + +template +inline constexpr bool + bpstd::detail::proxy_iterator::operator==(const proxy_iterator& rhs) + const noexcept +{ + return m_iter == rhs.m_iter; +} + +template +inline constexpr bool + bpstd::detail::proxy_iterator::operator!=(const proxy_iterator& rhs) + const noexcept +{ + return m_iter != rhs.m_iter; +} + +template +inline constexpr bool + bpstd::detail::proxy_iterator::operator<(const proxy_iterator& rhs) + const noexcept +{ + return m_iter < rhs.m_iter; +} + +template +inline constexpr bool + bpstd::detail::proxy_iterator::operator<=(const proxy_iterator& rhs) + const noexcept +{ + return m_iter <= rhs.m_iter; +} + +template +inline constexpr bool +bpstd::detail::proxy_iterator::operator>(const proxy_iterator& rhs) + const noexcept +{ + return m_iter > rhs.m_iter; +} + +template +inline constexpr bool +bpstd::detail::proxy_iterator::operator>=(const proxy_iterator& rhs) + const noexcept +{ + return m_iter >= rhs.m_iter; +} + +//============================================================================== +// definitions : non-member functions : class : proxy_iterator +//============================================================================== + +//------------------------------------------------------------------------------ +// Random Access (free functions) +//------------------------------------------------------------------------------ + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator + bpstd::detail::operator+(const proxy_iterator& lhs, + typename proxy_iterator::difference_type rhs) + noexcept +{ + return proxy_iterator{lhs} += rhs; +} + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator + bpstd::detail::operator+(typename proxy_iterator::difference_type lhs, + const proxy_iterator& rhs) + noexcept +{ + return proxy_iterator{rhs} += lhs; +} + +template +inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator + bpstd::detail::operator-(const proxy_iterator& lhs, + typename proxy_iterator::difference_type rhs) + noexcept +{ + return proxy_iterator{lhs} -= rhs; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_PROXY_ITERATOR_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/variant_base.hpp b/src/libs/vmisc/bpstd/detail/variant_base.hpp new file mode 100644 index 000000000..687c9f01c --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/variant_base.hpp @@ -0,0 +1,240 @@ +/***************************************************************************** + * \file variant_base.hpp + * + * \brief This internal header provides the definition of a utility for + * variant, variant_base + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_VARIANT_BASE_HPP +#define BPSTD_DETAIL_VARIANT_BASE_HPP + +#include "config.hpp" // BPSTD_CPP14_CONSTEXPR +#include "variant_union.hpp" // detail::variant_union + +#include // std::size_t +#include // std::forward + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + //========================================================================== + // class : variant_base + //========================================================================== + + //////////////////////////////////////////////////////////////////////////// + /// \brief The base class used by variant + //////////////////////////////////////////////////////////////////////////// + template + class variant_base; + + //========================================================================== + // class : variant_base + //========================================================================== + + template + class variant_base + { + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + public: + + constexpr variant_base(); + + template + constexpr variant_base(variant_index_tag, Args&&...args); + + //------------------------------------------------------------------------ + // Protected Members + //------------------------------------------------------------------------ + protected: + + variant_union m_union; + std::size_t m_index; + + //--------------------------------------------------------------------- + // Protected Member Functions + //--------------------------------------------------------------------- + protected: + + void destroy_active_object(); + }; + + //========================================================================== + // class : variant_base + //========================================================================== + + template + class variant_base + { + public: + + constexpr variant_base(); + + template + constexpr variant_base(variant_index_tag, Args&&...args); + + ~variant_base(); + + //--------------------------------------------------------------------- + // Protected Members + //--------------------------------------------------------------------- + protected: + + variant_union m_union; + std::size_t m_index; + + //--------------------------------------------------------------------- + // Protected Member Functions + //--------------------------------------------------------------------- + protected: + + void destroy_active_object(); + + //--------------------------------------------------------------------- + // Private Static Member Functions + //--------------------------------------------------------------------- + private: + + struct destroy_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& v) { + v.~T(); + } + }; + }; + + } // namespace detail +} // namespace bpstd + +//============================================================================== +// class : variant_base +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_base::variant_base() + : m_union{}, + m_index{static_cast(-1)} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_base::variant_base(variant_index_tag, + Args&&...args) + : m_union{variant_index_tag{}, std::forward(args)...}, + m_index{N} +{ + +} + +//------------------------------------------------------------------------------ +// Protected Members +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::variant_base::destroy_active_object() +{ + m_index = static_cast(-1); +} + +//============================================================================== +// class : variant_base +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors / Destructor +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_base::variant_base() + : m_union{}, + m_index{static_cast(-1)} +{ + +} + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4702) +#endif + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_base::variant_base(variant_index_tag, + Args&&...args) + : m_union{variant_index_tag{}, std::forward(args)...}, + m_index{N} +{ + +} + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::detail::variant_base::~variant_base() +{ + destroy_active_object(); +} + +//------------------------------------------------------------------------------ +// Protected Members +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::variant_base::destroy_active_object() +{ + if (m_index == static_cast(-1)) { + return; + } + + visit_union(m_index, destroy_visitor{}, m_union); + m_index = static_cast(-1); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_VARIANT_BASE_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/variant_fwds.hpp b/src/libs/vmisc/bpstd/detail/variant_fwds.hpp new file mode 100644 index 000000000..aba8339a0 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/variant_fwds.hpp @@ -0,0 +1,50 @@ +/***************************************************************************** + * \file variant_fwds.hpp + * + * \brief This internal header provides forward declarations of various + * variant types used internally + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_VARIANT_FWDS_HPP +#define BPSTD_DETAIL_VARIANT_FWDS_HPP + +namespace bpstd { + namespace detail { + + template + union variant_union; + + template + class variant_base; + + } // namespace detail + + template + class variant; + +} // namespace bpstd + +#endif /* BPSTD_DETAIL_VARIANT_FWDS_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/variant_traits.hpp b/src/libs/vmisc/bpstd/detail/variant_traits.hpp new file mode 100644 index 000000000..cb1354aa8 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/variant_traits.hpp @@ -0,0 +1,112 @@ +/***************************************************************************** + * \file variant_traits.hpp + * + * \brief This internal header provides forward declarations of various + * variant traits + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_VARIANT_TRAITS_HPP +#define BPSTD_DETAIL_VARIANT_TRAITS_HPP + +#include "config.hpp" +#include "variant_fwds.hpp" +#include "invoke.hpp" // invoke_result + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + template + struct variant_first_type; + + template + struct variant_first_type> + { + using type = Type0; + }; + + template + struct variant_first_type> + { + using type = Type0; + }; + + template + struct variant_first_type> + { + using type = Type0; + }; + + template + struct variant_first_type + { + using type = typename variant_first_type::type&; + }; + + template + struct variant_first_type + { + using type = typename variant_first_type::type&&; + }; + + template + struct variant_first_type + { + using type = const typename variant_first_type::type; + }; + + template + struct variant_first_type + { + using type = const typename variant_first_type::type&; + }; + + template + struct variant_first_type + { + using type = const typename variant_first_type::type&&; + }; + + template + using variant_first_type_t = typename variant_first_type::type; + + //-------------------------------------------------------------------------- + + template + struct variant_visitor_invoke_result + : invoke_result...>{}; + + template + using variant_visitor_invoke_result_t + = typename variant_visitor_invoke_result::type; + + } // namespace detail +} // namespace bpstd + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_VARIANT_TRAITS_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/variant_union.hpp b/src/libs/vmisc/bpstd/detail/variant_union.hpp new file mode 100644 index 000000000..0dcf68e72 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/variant_union.hpp @@ -0,0 +1,580 @@ +/***************************************************************************** + * \file variant_union.hpp + * + * \brief This internal header provides the definition of a utility for + * variant, variant_union + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_VARIANT_UNION_HPP +#define BPSTD_DETAIL_VARIANT_UNION_HPP + +#include "config.hpp" // BPSTD_CPP14_CONSTEXPR +#include "nth_type.hpp" // detail::nth_type +#include "move.hpp" // forward +#include "variant_traits.hpp" + +#include // std::size_t +#include // std::decay +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + template + struct match_cv { + using type = To; + }; + template + struct match_cv { + using type = const To; + }; + template + struct match_cv { + using type = volatile To; + }; + template + struct match_cv { + using type = const volatile To; + }; + + template + struct match_reference { + using type = To&&; + }; + + template + struct match_reference { + using type = To&&; + }; + + template + struct match_reference { + using type = To&; + }; + + template + using match_cvref = match_reference::type,To + >::type + >; + + template + using match_cvref_t = typename match_cvref::type; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A tag type used to represent an empty variant + //////////////////////////////////////////////////////////////////////////// + struct variant_empty{}; + + template + struct variant_index_tag{}; + + ///////////////////////////////////////////////////////////////////////////// + /// \brief Implementation of the variant_union class + /// + /// \tparam IsTrivial true if all the types in the variant are trivial + /// \tparam Types the types in the variant + //////////////////////////////////////////////////////////////////////////// + template + union variant_union; + + /// \brief A type-trait for retrieving the number of elements in a variant + /// union + template + struct variant_union_size + : variant_union_size::type>{}; + + template + struct variant_union_size> + : std::integral_constant{}; + + //========================================================================== + // union : variant_union + //========================================================================== + + // Partial specialization: All types are trivial; is trivially destructible + template + union variant_union + { + //------------------------------------------------------------------------ + // Public Members Types + //------------------------------------------------------------------------ + + using current_type = Type0; + using next_type = variant_union; + + //------------------------------------------------------------------------ + // Public Members + //------------------------------------------------------------------------ + + variant_empty empty; + current_type current; + next_type next; + + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + + constexpr variant_union(); + + template + constexpr variant_union(variant_index_tag<0>, Args&&...args); + + template + constexpr variant_union(variant_index_tag, Args&&...args); + }; + + //========================================================================== + // union : variant_union + //========================================================================== + + // Partial specialization: At least one type is not trivial + // This specialization needs to exist to explicitly define ~variant_union, + // but is otherwise the *only* difference + template + union variant_union + { + //------------------------------------------------------------------------ + // Public Members Types + //------------------------------------------------------------------------ + + using current_type = Type0; + using next_type = variant_union; + + //------------------------------------------------------------------------ + // Public Members + //------------------------------------------------------------------------ + + variant_empty empty; + current_type current; + next_type next; + + //------------------------------------------------------------------------ + // Constructors / Destructor + //------------------------------------------------------------------------ + + constexpr variant_union(); + + template + constexpr variant_union(variant_index_tag<0>, Args&&...args); + + template + constexpr variant_union(variant_index_tag, Args&&...args); + + ~variant_union(){} + }; + + //========================================================================== + // union : variant_union + //========================================================================== + + template + union variant_union + { + //------------------------------------------------------------------------ + // Public Members + //------------------------------------------------------------------------ + + variant_empty empty; + + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + + constexpr variant_union(); + + template + constexpr variant_union(variant_index_tag<0>); + }; + + //========================================================================== + // non-member functions : class : variant_union + //========================================================================== + + //-------------------------------------------------------------------------- + // Utilities + //-------------------------------------------------------------------------- + + /// \brief Visits the element in the variant_union \p v at index \p n + /// + /// \param n the index + /// \param fn the function to invoke on the underlying value + /// \param v the variant_union + template + BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t + visit_union(std::size_t n, Fn&& fn, VariantUnion&& v); + + /// \brief Visits the elements in the variant_union \p v1 and \p v2 at + /// index \p n + /// + /// \note it is assumed that \p n is the active member of both \p v1 and + /// \p v2 + /// + /// \param n the index + /// \param fn the function to invoke on the underlying value + /// \param v1 the first variant_union + /// \param v2 the second variant_union + template + BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t + visit_union(std::size_t n, Fn&& fn, VariantUnion&& v1, UVariantUnion&& v2); + + /// \{ + /// \brief Gets the element at index \p N out of the variant_union + /// + /// \tparam N the nth object to retrieve + /// \param u the union + /// \return the object at N + template + constexpr bpstd::detail::nth_type_t& + union_get(variant_union& u); + + template + constexpr const bpstd::detail::nth_type_t& + union_get(const variant_union& u); + + template + constexpr bpstd::detail::nth_type_t&& + union_get(variant_union&& u); + + template + constexpr const bpstd::detail::nth_type_t&& + union_get(const variant_union&& u); + /// \} + + } // namespace detail +} // namespace bpstd + +//============================================================================== +// union : variant_union +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors +//------------------------------------------------------------------------------ + +template +inline constexpr bpstd::detail::variant_union + ::variant_union() + : empty{} +{ + +} + +template +template +inline constexpr bpstd::detail::variant_union + ::variant_union(variant_index_tag<0>, Args&&...args) + : current(bpstd::forward(args)...) +{ + +} + +template +template +inline constexpr bpstd::detail::variant_union + ::variant_union(variant_index_tag, Args&&...args) + : next{variant_index_tag{}, bpstd::forward(args)...} +{ + +} + +//============================================================================== +// union : variant_union +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors +//------------------------------------------------------------------------------ + +template +inline constexpr bpstd::detail::variant_union + ::variant_union() + : empty{} +{ + +} + +template +template +inline constexpr bpstd::detail::variant_union + ::variant_union(variant_index_tag<0>, Args&&...args) + : current(bpstd::forward(args)...) +{ + +} + +template +template +inline constexpr bpstd::detail::variant_union + ::variant_union(variant_index_tag, Args&&...args) + : next{variant_index_tag{}, bpstd::forward(args)...} +{ + +} + +//============================================================================== +// union : variant_union +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_union::variant_union() + : empty{} +{ + // base-case; should never be executed +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::variant_union::variant_union(variant_index_tag<0>) + : empty{} +{ + // base-case; should never be executed +} + +//============================================================================== +// non-member functions : class : variant_union +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +namespace bpstd { namespace detail { + + // Single-case + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bpstd::detail::variant_visitor_invoke_result_t + do_visit_union(variant_index_tag<1>, + std::size_t n, + Fn&& fn, + VariantUnion&& v) + { + BPSTD_UNUSED(n); + + return bpstd::forward(fn)( + union_get<0>(bpstd::forward(v)) + ); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bpstd::detail::variant_visitor_invoke_result_t + do_visit_union(variant_index_tag, + std::size_t n, + Fn&& fn, + VariantUnion&& v) + { + using size_type = variant_union_size; + + if (n == 0) { + return bpstd::forward(fn)( + union_get<0>(bpstd::forward(v)) + ); + } + + return do_visit_union( + variant_index_tag<(size_type::value - 1)>{}, + n-1, + bpstd::forward(fn), + static_cast>(v.next) + ); + } + + // Double-case + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bpstd::detail::variant_visitor_invoke_result_t + do_visit_union(variant_index_tag<1>, + std::size_t n, + Fn&& fn, + VariantUnion&& v0, + UVariantUnion&& v1) + { + BPSTD_UNUSED(n); + + return bpstd::forward(fn)( + union_get<0>(bpstd::forward(v0)), + union_get<0>(bpstd::forward(v1)) + ); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bpstd::detail::variant_visitor_invoke_result_t + do_visit_union(variant_index_tag, + std::size_t n, + Fn&& fn, + VariantUnion&& v0, + UVariantUnion&& v1) + { + using size_type = variant_union_size; + + if (n == 0) { + return bpstd::forward(fn)( + union_get<0>(bpstd::forward(v0)), + union_get<0>(bpstd::forward(v1)) + ); + } + + return do_visit_union( + variant_index_tag<(size_type::value - 1)>{}, + n-1, + bpstd::forward(fn), + static_cast>(v0.next), + static_cast>(v1.next) + ); + } + + +}} // namespace bpstd::detail + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::detail::variant_visitor_invoke_result_t + bpstd::detail::visit_union(std::size_t n, Fn&& fn, VariantUnion&& v) +{ + using size_type = variant_union_size; + + return detail::do_visit_union( + variant_index_tag{}, + n, + bpstd::forward(fn), + bpstd::forward(v) + ); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::detail::variant_visitor_invoke_result_t + bpstd::detail::visit_union(std::size_t n, + Fn&& fn, + VariantUnion&& v1, + UVariantUnion&& v2) +{ + using size_type = variant_union_size; + + return detail::do_visit_union( + variant_index_tag{}, + n, + bpstd::forward(fn), + bpstd::forward(v1), + bpstd::forward(v2) + ); +} + +//------------------------------------------------------------------------------ + +namespace bpstd { namespace detail { + + // private implementation: recurse on index + + template + inline BPSTD_INLINE_VISIBILITY constexpr + nth_type_t& + do_union_get(variant_index_tag, variant_union& u) + { + return do_union_get(variant_index_tag{}, u.next); + } + template + inline BPSTD_INLINE_VISIBILITY constexpr + nth_type_t<0,Types...>& + do_union_get(variant_index_tag<0>, variant_union& u) + { + return u.current; + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + const nth_type_t& + do_union_get(variant_index_tag, const variant_union& u) + { + return do_union_get(variant_index_tag{}, u.next); + } + template + inline BPSTD_INLINE_VISIBILITY constexpr + const nth_type_t<0,Types...>& + do_union_get(variant_index_tag<0>, const variant_union& u) + { + return u.current; + } + +}} // namespace bpstd::detail + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::nth_type_t& + bpstd::detail::union_get(variant_union& u) +{ + static_assert(N < sizeof...(Types), "N index out of bounds"); + + return do_union_get(variant_index_tag{}, u); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const bpstd::detail::nth_type_t& + bpstd::detail::union_get(const variant_union& u) +{ + static_assert(N < sizeof...(Types), "N index out of bounds"); + + return do_union_get(variant_index_tag{}, u); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::nth_type_t&& + bpstd::detail::union_get(variant_union&& u) +{ + static_assert(N < sizeof...(Types), "N index out of bounds"); + + return bpstd::move(do_union_get(variant_index_tag{}, u)); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const bpstd::detail::nth_type_t&& + bpstd::detail::union_get(const variant_union&& u) +{ + static_assert(N < sizeof...(Types), "N index out of bounds"); + + return bpstd::move(do_union_get(variant_index_tag{}, u)); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_VARIANT_UNION_HPP */ diff --git a/src/libs/vmisc/bpstd/detail/variant_visitors.hpp b/src/libs/vmisc/bpstd/detail/variant_visitors.hpp new file mode 100644 index 000000000..de8996cf0 --- /dev/null +++ b/src/libs/vmisc/bpstd/detail/variant_visitors.hpp @@ -0,0 +1,195 @@ +/***************************************************************************** + * \file variant_visitors.hpp + * + * \brief This internal header provides the definition of various visitors for + * the variant. + * + * These variants are used internally to construct a variant. + *****************************************************************************/ + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_DETAIL_VARIANT_VISITORS_HPP +#define BPSTD_DETAIL_VARIANT_VISITORS_HPP + +#include "config.hpp" +#include "move.hpp" +#include "../tuple.hpp" // get +#include "../utility.hpp" // index_sequence + +#include // placement new +#include // std::swap + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + namespace detail { + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for copy-constructing an underlying variant from the + /// same active type from the other variant + //////////////////////////////////////////////////////////////////////////// + struct variant_copy_construct_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& self, const T& other) const + { + new (&self) T(other); + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for copy-assigning an underlying variant from the + /// same active type from the other variant + //////////////////////////////////////////////////////////////////////////// + struct variant_copy_assign_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& self, const T& other) const + { + self = other; + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for move-constructing an underlying variant from the + /// same active type from the other variant + //////////////////////////////////////////////////////////////////////////// + struct variant_move_construct_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& self, U&& other) const + { + new (&self) T(bpstd::forward(other)); + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for move-assign an underlying variant from the + /// same active type from the other variant + //////////////////////////////////////////////////////////////////////////// + struct variant_move_assign_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& self, U&& other) const + { + self = bpstd::forward(other); + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for swapping the underlying elements of a variant + //////////////////////////////////////////////////////////////////////////// + struct variant_swap_visitor + { + template + inline BPSTD_INLINE_VISIBILITY + void operator()(T& lhs, T& rhs) const + { + using std::swap; + swap(lhs,rhs); + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for assigning an element from T to the underlying + /// active variant alternative + //////////////////////////////////////////////////////////////////////////// + template + struct variant_assign_visitor + { + Arg m_value; + + template + inline BPSTD_INLINE_VISIBILITY + variant_assign_visitor(UArg&& u) + : m_value(bpstd::forward(u)) + { + + } + + template + inline BPSTD_INLINE_VISIBILITY + void operator()(U&) + { + } + + inline BPSTD_INLINE_VISIBILITY + void operator()(T& x) + { + x = static_cast(m_value); + } + }; + + //////////////////////////////////////////////////////////////////////////// + /// \brief A visitor for emplacing elements into a variant + //////////////////////////////////////////////////////////////////////////// + template + struct variant_emplace_visitor + { + Tuple m_tuple; + + template + inline BPSTD_INLINE_VISIBILITY + variant_emplace_visitor(UTuple&& tuple) + : m_tuple{bpstd::forward(tuple)} + { + + } + + template + inline BPSTD_INLINE_VISIBILITY + void operator()(U&) + { + } + + inline BPSTD_INLINE_VISIBILITY + void operator()(T& x) + { + emplace_from_tuple( + &x, + bpstd::move(m_tuple), + make_index_sequence::value>{} + ); + } + + template + inline BPSTD_INLINE_VISIBILITY + static void emplace_from_tuple(void* p, UTuple&& tuple, index_sequence) + { + new(p) T(std::get(bpstd::forward(tuple))...); + } + + }; + + } // namespace detail +} // namespace bpstd + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_DETAIL_VARIANT_VISITORS_HPP */ diff --git a/src/libs/vmisc/bpstd/exception.hpp b/src/libs/vmisc/bpstd/exception.hpp new file mode 100644 index 000000000..a69d4b9ef --- /dev/null +++ b/src/libs/vmisc/bpstd/exception.hpp @@ -0,0 +1,199 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file exception.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_EXCEPTION_HPP +#define BPSTD_EXCEPTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" + +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +// The large #if/endif block below, and the definition of +// bpstd::uncaught_exceptions is taken from boost: +// https://beta.boost.org/doc/libs/develop/boost/core/uncaught_exceptions.hpp + +// Copyright Andrey Semashev 2018. +// 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) + +#if (__cplusplus >= 201703L && defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411) || \ + defined(_MSC_VER) && _MSC_VER >= 1900 +# define BPSTD_HAS_UNCAUGHT_EXCEPTIONS +#endif + +#if !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) + +// cxxabi.h availability macro +# if defined(__has_include) +# if __has_include() +# define BPSTD_HAS_CXXABI_H +# endif +# elif defined(__GLIBCXX__) || defined(__GLIBCPP__) +# define BPSTD_HAS_CXXABI_H +# endif + +# if defined(BPSTD_HAS_CXXABI_H) +// MinGW GCC 4.4 seem to not work the same way the newer GCC versions do. As +// a result, __cxa_get_globals based implementation will always return 0. +// Just disable it for now and fall back to std::uncaught_exception(). +# if !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405)) +# include +# include +# define BPSTD_HAS_CXA_GET_GLOBALS + +// At least on MinGW and Linux, only GCC since 4.7 declares __cxa_get_globals() +// in cxxabi.h. Older versions of GCC do not expose this function but it's +// there. +// On OpenBSD, it seems, the declaration is also missing. +// Note that at least on FreeBSD 11, cxxabi.h declares __cxa_get_globals with +// a different exception specification, so we can't declare the function +// unconditionally. On Linux with clang and libc++ and on OS X, there is a +// version of cxxabi.h from libc++abi that doesn't declare __cxa_get_globals, +// but provides __cxa_uncaught_exceptions. +// The function only appeared in version _LIBCPPABI_VERSION >= 1002 of the +// library. Unfortunately, there are linking errors about undefined reference +// to __cxa_uncaught_exceptions on Ubuntu Trusty and OS X, so we avoid using +// it and forward-declare __cxa_get_globals instead. On QNX SDP 7.0 (QCC 5.4.0), +// there are multiple cxxabi.h, one from glibcxx from gcc and another from +// libc++abi from LLVM. Which one is included will be determined by the qcc +// command line arguments (-V and/or -Y; +// http://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html +// ). +// The LLVM libc++abi is missing the declaration of __cxa_get_globals but it is +// also patched by QNX developers to not define _LIBCPPABI_VERSION. Older QNX +// SDP versions, up to and including 6.6, don't provide LLVM and libc++abi. +// See https://github.com/boostorg/core/issues/59. +# if !defined(__FreeBSD__) && \ + ( \ + (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || \ + defined(__OpenBSD__) || \ + (defined(__QNXNTO__) && !defined(__GLIBCXX__) && !defined(__GLIBCPP__)) || \ + defined(_LIBCPPABI_VERSION) \ + ) +namespace __cxxabiv1 { + struct __cxa_eh_globals; +# if defined(__OpenBSD__) + extern "C" __cxa_eh_globals* __cxa_get_globals(); +# else + extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept __attribute__((__const__)); +# endif +} // namespace __cxxabiv1 +# endif +# endif // !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405)) +# endif // defined(BPSTD_HAS_CXXABI_H) + +# if defined(_MSC_VER) && _MSC_VER >= 1400 +# include +# define BPSTD_HAS_GETPTD +namespace scope { + namespace detail { + extern "C" void* _getptd(); + } // namespace detail +} // namespace scope +# endif // defined(_MSC_VER) && _MSC_VER >= 1400 +#endif // !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) + +#if !defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) && \ + !defined(BPSTD_HAS_CXA_GET_GLOBALS) && \ + !defined(BPSTD_HAS_GETPTD) +//! This macro is defined when `uncaught_exceptions` is not guaranteed to +//! return values greater than 1 if multiple exceptions are pending +# define BPSTD_UNCAUGHT_EXCEPTIONS_EMULATED +#endif + +namespace bpstd { + + //============================================================================ + // non-member functions + //============================================================================ + + /// \brief Returns the number of exceptions currently in-flight in the current + /// frame + /// + /// \return the number of exceptions + int uncaught_exceptions() noexcept; + +} // namespace bpstd + +//============================================================================== +// definitions : non-member functions +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +inline BPSTD_INLINE_VISIBILITY +int bpstd::uncaught_exceptions() + noexcept +{ +#if defined(BPSTD_HAS_UNCAUGHT_EXCEPTIONS) + // C++17 implementation + return std::uncaught_exceptions(); +#elif defined(BPSTD_HAS_CXA_GET_GLOBALS) + // Tested on {clang 3.2,GCC 3.5.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64} + using byte = unsigned char; + auto count = int{}; + const auto* ptr = reinterpret_cast(::abi::__cxa_get_globals()) + sizeof(void*); + + // __cxa_eh_globals::uncaughtExceptions, x32 offset - 0x4, x64 - 0x8 + std::memcpy(&count, ptr, sizeof(count)); + return count; +#elif defined(BPSTD_HAS_GETPTD) + // MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}. + using byte = unsigned char; + auto count = int{}; + + const auto offset = (sizeof(void*) == 8u ? 0x100 : 0x90); + const auto* ptr = static_cast(::scope::detail::_getptd()) + offset; + + // _tiddata::_ProcessingThrow, x32 offset - 0x90, x64 - 0x100 + std::memcpy(&count, ptr, sizeof(count)); + return count; +#else + // Portable C++03 implementation. Does not allow to detect multiple + // nested exceptions. + + // This is a buggy fallback since it will only work with 1 exception + // in-flight, but we don't have any other options without exploiting + // internal compiler features. + return static_cast(std::uncaught_exception()); +#endif +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_EXCEPTION_HPP */ diff --git a/src/libs/vmisc/bpstd/functional.hpp b/src/libs/vmisc/bpstd/functional.hpp new file mode 100644 index 000000000..b063b1378 --- /dev/null +++ b/src/libs/vmisc/bpstd/functional.hpp @@ -0,0 +1,699 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file functional.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_FUNCTIONAL_HPP +#define BPSTD_FUNCTIONAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "type_traits.hpp" +#include "utility.hpp" +#include "detail/invoke.hpp" + +#include // to proxy API + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + /// \brief Invoke the Callable object \p function with the parameters \p args. + /// + /// As by \c INVOKE(std::forward(f), std::forward(args)...) + /// + /// \param function Callable object to be invoked + /// \param args arguments to pass to \p function + template + constexpr invoke_result_t invoke(Func&& function, Args&&... args) + noexcept(is_nothrow_invocable::value); + + namespace detail { + template + struct not_fn_t + { + Fn fn; + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + auto operator()(Args&&... args) & + noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward(args)...))) + -> decltype(!::bpstd::invoke(fn, ::bpstd::forward(args)...)) + { + return !::bpstd::invoke(fn, bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + auto operator()(Args&&... args) && + noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward(args)...))) + -> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward(args)...)) + { + return !::bpstd::invoke(std::move(fn), bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(Args&&... args) const& + noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward(args)...))) + -> decltype(!::bpstd::invoke(fn, ::bpstd::forward(args)...)) + { + return !::bpstd::invoke(fn, bpstd::forward(args)...); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(Args&&... args) const&& + noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward(args)...))) + -> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward(args)...)) + { + return !::bpstd::invoke(std::move(fn), bpstd::forward(args)...); + } + }; + } // namespace detail + + /// \brief Creates a forwarding call wrapper that returns the negation of the + /// callable object it holds. + /// + /// \param fn the object from which the Callable object held by the wrapper + /// is constructed + /// \return the negated object + template + constexpr detail::not_fn_t> not_fn(Fn&& fn); + + //============================================================================ + // struct : plus + //============================================================================ + + template + struct plus + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs + rhs; + } + }; + + template <> + struct plus + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) + ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) + bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : minus + //============================================================================ + + template + struct minus + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs - rhs; + } + }; + + template <> + struct minus + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) - ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) - bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : multiplies + //============================================================================ + + template + struct multiplies + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs * rhs; + } + }; + + template <> + struct multiplies + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) * ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) * bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : divides + //============================================================================ + + template + struct divides + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs / rhs; + } + }; + + template <> + struct divides + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) / ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) / bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : modulus + //============================================================================ + + template + struct modulus + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs % rhs; + } + }; + + template <> + struct modulus + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) % ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) % bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : negate + //============================================================================ + + template + struct negate + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& arg) + const + { + return -arg; + } + }; + + template <> + struct negate + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& arg) const + -> decltype(-::bpstd::forward(arg)) + { + return -bpstd::forward(arg); + } + }; + + //============================================================================ + // struct : equal_to + //============================================================================ + + template + struct equal_to + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs == rhs; + } + }; + + template <> + struct equal_to + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) == ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) == bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : not_equal_to + //============================================================================ + + template + struct not_equal_to + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs != rhs; + } + }; + + template <> + struct not_equal_to + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) != ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) != bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : greater + //============================================================================ + + template + struct greater + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs > rhs; + } + }; + + template <> + struct greater + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) > ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) > bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : greater_equal + //============================================================================ + + template + struct greater_equal + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs >= rhs; + } + }; + + template <> + struct greater_equal + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) >= ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) >= bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : less + //============================================================================ + + template + struct less + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs < rhs; + } + }; + + template <> + struct less + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) < ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) < bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : less_equal + //============================================================================ + + template + struct less_equal + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs <= rhs; + } + }; + + template <> + struct less_equal + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) <= ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) <= bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : logical_and + //============================================================================ + + template + struct logical_and + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs && rhs; + } + }; + + template <> + struct logical_and + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) && ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) && bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : logical_or + //============================================================================ + + template + struct logical_or + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& lhs, const T& rhs) + const + { + return lhs || rhs; + } + }; + + template <> + struct logical_or + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) || ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) || bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : logical_not + //============================================================================ + + template + struct logical_not + { + inline BPSTD_INLINE_VISIBILITY constexpr + bool operator()(const T& arg) + const + { + return !arg; + } + }; + + template <> + struct logical_not + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& arg) const + -> decltype(!::bpstd::forward(arg)) + { + return !bpstd::forward(arg); + } + }; + + //============================================================================ + // struct : bit_and + //============================================================================ + + template + struct bit_and + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs & rhs; + } + }; + + template <> + struct bit_and + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) & ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) & bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : bit_or + //============================================================================ + + template + struct bit_or + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs | rhs; + } + }; + + template <> + struct bit_or + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) | ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) | bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : bit_xor + //============================================================================ + + template + struct bit_xor + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& lhs, const T& rhs) + const + { + return lhs ^ rhs; + } + }; + + template <> + struct bit_xor + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& lhs, U&& rhs) const + -> decltype(::bpstd::forward(lhs) ^ ::bpstd::forward(rhs)) + { + return bpstd::forward(lhs) ^ bpstd::forward(rhs); + } + }; + + //============================================================================ + // struct : bit_not + //============================================================================ + + template + struct bit_not + { + inline BPSTD_INLINE_VISIBILITY constexpr + T operator()(const T& arg) + const + { + return ~arg; + } + }; + + template <> + struct bit_not + { + using is_transparent = true_type; + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto operator()(T&& arg) const + -> decltype(~::bpstd::forward(arg)) + { + return ~bpstd::forward(arg); + } + }; + +} // namespace bpstd + +//============================================================================== +// definition : invoke +//============================================================================== + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::invoke_result_t bpstd::invoke(Func&& function, Args&&... args) + noexcept(is_nothrow_invocable::value) +{ + return detail::INVOKE(bpstd::forward(function), bpstd::forward(args)...); +} + + +//============================================================================== +// definition : not_fn +//============================================================================== + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::not_fn_t> bpstd::not_fn(Fn&& fn) +{ + static_assert( + is_move_constructible::value, + "Fn must be move constructible" + ); + static_assert( + is_constructible,Fn>::value, + "Fn must be constructible from an instance of fn" + ); + + return { bpstd::forward(fn) }; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_FUNCTIONAL_HPP */ diff --git a/src/libs/vmisc/bpstd/iterator.hpp b/src/libs/vmisc/bpstd/iterator.hpp new file mode 100644 index 000000000..b92cbeabb --- /dev/null +++ b/src/libs/vmisc/bpstd/iterator.hpp @@ -0,0 +1,278 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file iterator.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_ITERATOR_HPP +#define BPSTD_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "type_traits.hpp" // common_type_t + +#include +#include // std::size_t +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // class : reverse_iterator + //============================================================================ + + template + using reverse_iterator = std::reverse_iterator; + + //============================================================================ + // non-member functions : class : reverse_iterator + //============================================================================ + + /// \brief Makes a reverse_iterator given an iterator \p i + /// + /// This is a convenience function template that constructs a + /// reverse_iterator for the given iterator \p i with the type deduced from + /// the type of the argument. + /// + /// \param i the iterator + /// \return the reverse_iterator + template + constexpr reverse_iterator make_reverse_iterator(Iterator i); + + //============================================================================ + // non-member functions + //============================================================================ + + /// \{ + /// \brief Gets a pointer to the data from \p c + /// + /// \param c the container to get the data pointe rrom + /// \return a pointer to the data + template + constexpr auto data(C& c) -> decltype(c.data()); + template + constexpr auto data(const C& c) -> decltype(c.data()); + /// \} + + /// \brief Gets a pointer to the start of an array + /// + /// \param array the array to get the pointer to + /// \return a pointer to the data + template + constexpr T* data(T (&array)[N]) noexcept; + + /// \brief Gets a pointer to the start of an initializer list + /// + /// \param il the initializer list + /// \return a pointer to the start of the initializer list + template + constexpr const E* data(std::initializer_list il) noexcept; + + //---------------------------------------------------------------------------- + + /// \brief Queries whether \p c is empty + /// + /// \param c the container to query + /// \return true if \p is empty + template + constexpr auto empty(const C& c) -> decltype(c.empty()); + + /// \brief Queries whether the array is empty + /// + /// \param array the array to check + /// \return true if N is 0 + template + constexpr bool empty(const T (&array)[N]) noexcept; + + /// \brief Queries whether an initializer list is empty + /// + /// \param il the initializer list to check + /// \return true if \p il is empty + template + constexpr bool empty(std::initializer_list il) noexcept; + + //---------------------------------------------------------------------------- + + /// \brief Gets the size of a container + /// + /// \param c the container to check + /// \return the container's size + template + constexpr auto size(const C& c) -> decltype(c.size()); + + /// \brief Gets the size of an array + /// + /// \param array the array to get the size from + /// \return the size of an array + template + constexpr std::size_t size(const T (&array)[N]) noexcept; + + //---------------------------------------------------------------------------- + + /// \brief Gets the signed-size of a container + /// + /// \param c the container to get the size from + /// \return the size of the container + template + constexpr auto ssize(const C& c) + -> common_type_t>; + + /// \brief Gets the signed size of an array + /// + /// \param array the array to get the size from + /// \return the size of an array + template + constexpr std::ptrdiff_t ssize(const T (&array)[N]) noexcept; + +} // namespace bpstd + +//============================================================================== +// non-member functions : class : reverse_iterator +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr + bpstd::reverse_iterator + bpstd::make_reverse_iterator(Iterator i) +{ + return reverse_iterator{i}; +} + +//============================================================================== +// non-member functions +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr + auto bpstd::data(C& c) + -> decltype(c.data()) +{ + return c.data(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + auto bpstd::data(const C& c) + -> decltype(c.data()) +{ + return c.data(); +} +template +inline BPSTD_INLINE_VISIBILITY constexpr + T* bpstd::data(T (&array)[N]) + noexcept +{ + return array; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + const E* bpstd::data(std::initializer_list il) + noexcept +{ + return il.begin(); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr + auto bpstd::empty(const C& c) + -> decltype(c.empty()) +{ + return c.empty(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + bool bpstd::empty(const T (&)[N]) + noexcept +{ + return N == 0; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + bool bpstd::empty(std::initializer_list il) + noexcept +{ + return il.begin() == il.end(); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr + auto bpstd::size(const C& c) + -> decltype(c.size()) +{ + return c.size(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + std::size_t bpstd::size(const T (&)[N]) + noexcept +{ + return N; +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr + auto bpstd::ssize(const C& c) + -> bpstd::common_type_t> +{ + using type = bpstd::common_type_t>; + + return static_cast(c.size()); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr + std::ptrdiff_t bpstd::ssize(const T (&)[N]) + noexcept +{ + return N; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_ITERATOR_HPP */ diff --git a/src/libs/vmisc/bpstd/memory.hpp b/src/libs/vmisc/bpstd/memory.hpp new file mode 100644 index 000000000..1bcfad3b0 --- /dev/null +++ b/src/libs/vmisc/bpstd/memory.hpp @@ -0,0 +1,261 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file memory.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_MEMORY_HPP +#define BPSTD_MEMORY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "type_traits.hpp" // conditional_t, void_t +#include "utility.hpp" // forward + +#include // std::unique_ptr +#include // std::size_t +#include // std::declval + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + namespace detail { + template + struct make_unique_result + { + using object = T; + }; + template + struct make_unique_result + { + using unbounded_array = T[]; + }; + template + struct make_unique_result + { + using bounded_array = T[N]; + }; + } + + /// \brief Constructs an object of type T and wraps it in a std::unique_ptr + /// + /// Constructs a non-array type T. The arguments args are passed to the + /// constructor of T. This overload only participates in overload resolution + /// if T is not an array type. + /// + /// \tparam T the type to construct + /// \param args the arguments to forward to T's constructor + /// \return the unique_ptr + template + std::unique_ptr::object> + make_unique(Args&&...args); + + /// \brief Constructs an object of type T[] and wraps it in a std::unique_ptr + /// + /// Constructs an array of unknown bound T. This overload only participates + /// in overload resolution if T is an array of unknown bound. + /// + /// \tparam T the type to construct + /// \param size the size of the array + /// \return the unique_ptr + template + std::unique_ptr::unbounded_array> + make_unique(std::size_t size); + + // Construction of arrays of known bound is disallowed + template + std::unique_ptr::bounded_array> + make_unique() = delete; + + /// \brief Constructs an object of type T through default-initialization + /// and wraps it in a std::unique_ptr + /// + /// Constructs a non-array type T. This overload only participates in + /// overload resolution if T is not an array type. The object is + /// default-initialised, which may mean it will need to be overwritten before + /// it is legal to be read + /// + /// \tparam T the type to construct + /// \return the unique_ptr + template + std::unique_ptr::object> + make_unique_for_overwrite(); + + /// \brief Constructs an object of type T[] through default-initialization + /// and wraps it in a std::unique_ptr + /// + /// Constructs an array of unknown bound T. This overload only participates + /// in overload resolution if T is an array of unknown bound. The array is + /// default-initialised, which may mean it will need to be overwritten before + /// it is legal to be read + /// + /// \tparam T the type to construct + /// \return the unique_ptr + template + std::unique_ptr::unbounded_array> + make_unique_for_overwrite(std::size_t size); + + // Construction of arrays of known bound is disallowed + template + std::unique_ptr::bounded_array> + make_unique_for_overwrite() = delete; + + //---------------------------------------------------------------------------- + + namespace detail { + + template + struct has_to_address : false_type{}; + + template + struct has_to_address::to_address(std::declval()))>> + : true_type{}; + + //-------------------------------------------------------------------------- + + template + struct operator_deref + { + using type = decltype(std::declval().operator->()); + }; + + template + struct operator_deref{}; + + //-------------------------------------------------------------------------- + + template + struct to_address_result + : operator_deref>::value, T>{}; + + template + struct to_address_result::to_address(std::declval()))>> + { + using type = decltype(std::pointer_traits::to_address(std::declval())); + }; + + template + using to_address_result_t = typename to_address_result::type; + + } // namespace detail + + /// \{ + /// \brief Converts a pointer-like type to a raw pointer by recursively + /// calling to_address on it + /// + /// \param p the pointer-like type + /// \return the pointer + template + constexpr T* to_address(T* p) noexcept; + template + constexpr detail::to_address_result_t to_address(const T& p) noexcept; + /// \} + +} // namespace bpstd + +template +inline BPSTD_INLINE_VISIBILITY +std::unique_ptr::object> + bpstd::make_unique(Args&&...args) +{ + return std::unique_ptr{new T(bpstd::forward(args)...)}; +} + +template +inline BPSTD_INLINE_VISIBILITY +std::unique_ptr::unbounded_array> + bpstd::make_unique(std::size_t size) +{ + return std::unique_ptr{new remove_extent_t[size]()}; +} + +template +inline BPSTD_INLINE_VISIBILITY +std::unique_ptr::object> + bpstd::make_unique_for_overwrite() +{ + return std::unique_ptr{new T}; +} + +template +inline BPSTD_INLINE_VISIBILITY +std::unique_ptr::unbounded_array> + bpstd::make_unique_for_overwrite(std::size_t size) +{ + return std::unique_ptr{new remove_extent_t[size]}; +} + +namespace bpstd { + namespace detail { + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto to_address_impl(const T& p, std::true_type) + -> decltype(std::pointer_traits::to_address(std::declval())) + { + return to_address(std::pointer_traits::to_address(p)); + } + + template + inline BPSTD_INLINE_VISIBILITY constexpr + auto to_address_impl(const T& p, std::false_type) + -> decltype(std::declval().operator->()) + { + return to_address(p.operator->()); + } + + } // namespace detail +} // namespace bpstd + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T* bpstd::to_address(T* p) + noexcept +{ + static_assert( + !std::is_function::value, + "T* must not be a function pointer" + ); + + return p; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::to_address_result_t + bpstd::to_address(const T& p) + noexcept +{ + return detail::to_address_impl(p, detail::has_to_address{}); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_MEMORY_HPP */ diff --git a/src/libs/vmisc/bpstd/optional.hpp b/src/libs/vmisc/bpstd/optional.hpp new file mode 100644 index 000000000..e159c6ce5 --- /dev/null +++ b/src/libs/vmisc/bpstd/optional.hpp @@ -0,0 +1,1774 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file optional.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_OPTIONAL_HPP +#define BPSTD_OPTIONAL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "detail/enable_overload.hpp" // enable_overload_if, disable_overload_if + +#include "utility.hpp" // in_place_t, forward, move +#include "functional.hpp" // invoke_result_t +#include "type_traits.hpp" + +#include // std::initializer_list +#include // enable_if +#include // std::logic_error +#include // placement new + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + template class optional; + + namespace detail { + + //========================================================================== + // trait : is_optional + //========================================================================== + + template + using optional_is_convertible = conjunction< + std::is_constructible&>, + std::is_constructible&>, + std::is_constructible&&>, + std::is_constructible&&>, + std::is_convertible&, T>, + std::is_convertible&, T>, + std::is_convertible&&, T>, + std::is_convertible&&, T> + >; + + template + using optional_is_copy_convertible = conjunction< + optional_is_convertible, + std::is_constructible + >; + + template + using optional_is_move_convertible = conjunction< + optional_is_convertible, + std::is_constructible + >; + + template + using optional_is_value_convertible = conjunction< + std::is_constructible, + negation,in_place_t>>, + negation,optional>> + >; + + template + using optional_is_convert_assignable = conjunction< + optional_is_convertible, + std::is_assignable&>, + std::is_assignable&>, + std::is_assignable&&>, + std::is_assignable&&> + >; + + template + using optional_is_copy_convert_assignable = conjunction< + optional_is_convert_assignable, + std::is_constructible, + std::is_assignable + >; + + template + using optional_is_move_convert_assignable = conjunction< + optional_is_convert_assignable, + std::is_constructible, + std::is_assignable + >; + + template + using optional_is_value_assignable = conjunction< + negation,optional>>, + std::is_constructible, + std::is_assignable, + disjunction< + negation,T>>, + negation> + > + >; + + } // namespace detail + + //========================================================================= + // class : bad_optional_access + //========================================================================= + + /////////////////////////////////////////////////////////////////////////// + /// \brief An exception thrown when an optional is attempted to be accessed + /// while not containing a value + /////////////////////////////////////////////////////////////////////////// + class bad_optional_access : public std::logic_error + { + public: + bad_optional_access() : std::logic_error("bad_optional_access"){} + }; + + //========================================================================= + // struct : nullopt_t + //========================================================================= + + /// \brief This type represents null optional value + struct nullopt_t + { + nullopt_t() = delete; + constexpr explicit nullopt_t(int) noexcept{} + }; + + //------------------------------------------------------------------------- + + /// \brief Instance of a nullopt type + constexpr nullopt_t nullopt = nullopt_t{0}; + + //========================================================================= + // class : optional + //========================================================================= + + namespace detail { + + template class optional_base; + + template + class optional_base + { + //--------------------------------------------------------------------- + // Constructors / Assignment + //--------------------------------------------------------------------- + public: + // cppcheck-suppress noExplicitConstructor + constexpr optional_base(nullopt_t) noexcept; + + template + constexpr optional_base(in_place_t, Args&&...args) + noexcept(std::is_nothrow_constructible::value); + + optional_base(optional_base&& other) = default; + optional_base(const optional_base& other) = default; + + //--------------------------------------------------------------------- + + optional_base& operator=(optional_base&& other) = default; + optional_base& operator=(const optional_base& other) = default; + + //--------------------------------------------------------------------- + // Protected Modifiers + //--------------------------------------------------------------------- + protected: + + BPSTD_CPP14_CONSTEXPR T* val() noexcept; + constexpr const T* val() const noexcept; + + constexpr bool contains_value() const noexcept; + + //--------------------------------------------------------------------- + // Protected Observers + //--------------------------------------------------------------------- + protected: + + template + void construct(Args&&...args); + + void destruct(); + + //--------------------------------------------------------------------- + // Private Member Types + //--------------------------------------------------------------------- + private: + + struct empty{}; + union storage_type { + empty nothing; + T something; + + template + constexpr storage_type(in_place_t, Args&&...args) + : something(bpstd::forward(args)...){} + constexpr storage_type() : nothing(){} + }; + + //--------------------------------------------------------------------- + // Private Members + //--------------------------------------------------------------------- + private: + + storage_type m_storage; + bool m_engaged; + }; + + template + class optional_base + { + //--------------------------------------------------------------------- + // Protected Constructors / Destructor / Assignment + //--------------------------------------------------------------------- + protected: + + // cppcheck-suppress noExplicitConstructor + optional_base(nullopt_t) noexcept; + + template + optional_base(in_place_t, Args&&...args) + noexcept(std::is_nothrow_constructible::value); + + optional_base(optional_base&& other) = default; + optional_base(const optional_base& other) = default; + + //--------------------------------------------------------------------- + + ~optional_base() noexcept(std::is_nothrow_destructible::value); + + //--------------------------------------------------------------------- + + optional_base& operator=(optional_base&& other) = default; + optional_base& operator=(const optional_base& other) = default; + + //--------------------------------------------------------------------- + // Protected Observers + //--------------------------------------------------------------------- + protected: + + T* val() noexcept; + const T* val() const noexcept; + bool contains_value() const noexcept; + + //--------------------------------------------------------------------- + // Protected Modifiers + //--------------------------------------------------------------------- + protected: + + template + void construct(Args&&...args); + void destruct(); + + //--------------------------------------------------------------------- + // Private Member Types + //--------------------------------------------------------------------- + private: + + struct empty{}; + union storage_type { + empty nothing; + T something; + + template + storage_type(in_place_t, Args&&...args) + : something(bpstd::forward(args)...){} + storage_type() : nothing(){} + ~storage_type(){} + }; + + //--------------------------------------------------------------------- + // Private Members + //--------------------------------------------------------------------- + private: + + storage_type m_storage; + bool m_engaged; + }; + } // namespace detail + + /////////////////////////////////////////////////////////////////////////// + /// \brief The class template optional manages an optional contained value, + /// i.e. a value that may or may not be present. + /// + /// A common use case for optional is the return value of a function that + /// may fail. As opposed to other approaches, such as std::pair, + /// optional handles expensive to construct objects well and is more + /// readable, as the intent is expressed explicitly. + /// + /// Any instance of optional at any given point in time either contains + /// a value or does not contain a value. + /// + /// If an optional contains a value, the value is guaranteed to be + /// allocated as part of the optional object footprint, i.e. no dynamic + /// memory allocation ever takes place. Thus, an optional object models an + /// object, not a pointer, even though the operator*() and operator->() + /// are defined. + /// + /// When an object of type optional is contextually converted to bool, + /// the conversion returns true if the object contains a value and false if + /// it does not contain a value. + /// + /// The optional object contains a value in the following conditions: + /// - The object is initialized with a value of type T + /// - The object is assigned from another optional that contains a value. + /// - The object does not contain a value in the following conditions: + /// - The object is default-initialized. + /// - The object is initialized with a value of nullopt_t or an optional + /// object that does not contain a value. + /// - The object is assigned from a value of nullopt_t or from an optional + /// that does not contain a value + /// + /// \tparam T the underlying type + /////////////////////////////////////////////////////////////////////////// + template + class optional + : detail::optional_base::value> + { + static_assert( + !std::is_void::value, + "optional is ill-formed" + ); + static_assert( + !std::is_reference::value, + "optional is ill-formed" + ); + static_assert( + !std::is_abstract::value, + "optional of an abstract-type is ill-formed" + ); + + using base_type = detail::optional_base::value>; + + //----------------------------------------------------------------------- + // Public Member Types + //----------------------------------------------------------------------- + public: + + using value_type = T; ///< The underlying type of this Optional + + //----------------------------------------------------------------------- + // Constructor / Destructor / Assignment + //----------------------------------------------------------------------- + public: + + /// \{ + /// \brief Constructs an optional that does not contain a value + constexpr optional() noexcept; + // cppcheck-suppress noExplicitConstructor + constexpr optional(nullopt_t) noexcept; + /// \} + + /// \brief Copy constructs an optional + /// + /// If \p other contains a value, initializes the contained value as if + /// direct-initializing (but not direct-list-initializing) an object of + /// type T with the expression *other. + /// + /// If other does not contain a value, constructs an object that does + /// not contain a value. + /// + /// \note This constructor is defined as deleted if std::is_copy_constructible_v is false + /// + /// \param other the optional to copy + // cppcheck-suppress noExplicitConstructor + optional(detail::enable_overload_if_t::value,const optional&> other); + optional(detail::disable_overload_if_t::value,const optional&> other) = delete; + + /// \brief Move constructs an optional + /// + /// If other contains a value, initializes the contained value as if + /// direct-initializing (but not direct-list-initializing) an object + /// of type T with the expression std::move(*other) and does not make + /// other empty: a moved-from optional still contains a value, but the + /// value itself is moved from. + /// + /// If other does not contain a value, constructs an object that does + /// not contain a value. + /// + /// \note This constructor is defined as deleted if std::is_move_constructible_v is false + /// + /// \param other the optional to move + // cppcheck-suppress noExplicitConstructor + optional(detail::enable_overload_if_t::value,optional&&> other); + optional(detail::disable_overload_if_t::value,optional&&> other) = delete; + + /// \{ + /// \brief Converting copy constructor + /// + /// If other doesn't contain a value, constructs an optional object + /// that does not contain a value. Otherwise, constructs an optional + /// object that contains a value, initialized as if direct-initializing + /// (but not direct-list-initializing) an object of type T with the + /// expression *other. + /// + /// \note This constructor does not participate in overload resolution + /// unless the following conditions are met: + /// - std::is_constructible_v is true + /// - T is not constructible or convertible from any expression + /// of type (possibly const) optional, i.e., the + /// following 8 type traits are all false: + /// - std::is_constructible_v&> + /// - std::is_constructible_v&> + /// - std::is_constructible_v&&> + /// - std::is_constructible_v&&> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_convertible_v&&, T> + /// + /// \note This constructor is explicit if and only if + /// std::is_convertible_v is false + /// + /// \param other the other type to convert + template ::value && std::is_convertible::value>* =nullptr> + // cppcheck-suppress noExplicitConstructor + optional(const optional& other); + template ::value && !std::is_convertible::value>* =nullptr> + explicit optional(const optional& other); + /// \} + + /// \{ + /// \brief Converting move constructor + /// + /// If other doesn't contain a value, constructs an optional object + /// that does not contain a value. Otherwise, constructs an optional + /// object that contains a value, initialized as if direct-initializing + /// (but not direct-list-initializing) an object of type T with the + /// expression std::move(*other). + /// + /// \note This constructor does not participate in overload resolution + /// unless the following conditions are met: + /// - std::is_constructible_v is true + /// - T is not constructible or convertible from any expression + /// of type (possibly const) optional, i.e., the + /// following 8 type traits are all false: + /// - std::is_constructible_v&> + /// - std::is_constructible_v&> + /// - std::is_constructible_v&&> + /// - std::is_constructible_v&&> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_convertible_v&&, T> + /// + /// \note This constructor is explicit if and only if + /// std::is_convertible_v is false + /// + /// \param other the other optional to move + template ::value && std::is_convertible::value>* =nullptr> + // cppcheck-suppress noExplicitConstructor + optional(optional&& other); + template ::value && !std::is_convertible::value>* =nullptr> + explicit optional(optional&& other); + /// \} + + /// \brief Constructs an optional object that contains a value + /// + /// the value is initialized as if direct-initializing (but not + /// direct-list-initializing) an object of type T from the arguments + /// std::forward(args)... + /// + /// \param args the arguments to pass to T's constructor + template ::value>> + constexpr explicit optional(in_place_t, Args&&... args); + + /// \brief Constructs an optional object that contains a value + /// + /// The value is initialized as if direct-initializing (but not + /// direct-list-initializing) an object of type T from the arguments + /// std::forward>(ilist), std::forward(args)... + /// + /// \param ilist An initializer list of entries to forward + /// \param args the arguments to pass to T's constructor + template &, Args...>::value>> + constexpr explicit optional(in_place_t, + std::initializer_list ilist, + Args&&...args); + + /// \{ + /// \brief Constructs an optional object that contains a value + /// + /// The value is initialized as if direct-initializing (but not + /// direct-list-initializing) an object of type T with the expression + /// value. + /// + /// \note This constructor is constexpr if the constructor of T + /// selected by direct-initialization is constexpr + /// + /// \note This constructor does not participate in overload + /// resolution unless std::is_constructible_v is true + /// and decay_t is neither std::in_place_t nor + /// optional. + /// + /// \note This constructor is explicit if and only if + /// std::is_convertible_v is false + /// + /// \param value the value to copy + template ::value && std::is_convertible::value>* =nullptr> + // cppcheck-suppress noExplicitConstructor + constexpr optional(U&& value); + template ::value && !std::is_convertible::value>* =nullptr> + constexpr explicit optional(U&& value); + /// \} + + //----------------------------------------------------------------------- + + /// \brief Assigns this optional to be a null optional + /// + /// If \c (*this) had a value before the call, the contained value is + /// destroyed. + optional& operator=(nullopt_t); + + /// \brief Copy assigns the optional stored in \p other + /// + /// \param other the other optional to copy + optional& operator=(detail::enable_overload_if_t::value && std::is_copy_assignable::value,const optional&> other); + optional& operator=(detail::disable_overload_if_t::value && std::is_copy_assignable::value,const optional&> other) = delete; + + /// \brief Move assigns the optional stored in \p other + /// + /// \note If \p other contained a value before the call, it is left as a + /// null optional + /// + /// \remark This assignment does not participate in overload resolution + /// unless U is + /// + /// \param other the other optional to move + optional& operator=(detail::enable_overload_if_t::value && std::is_move_assignable::value,optional&&> other); + optional& operator=(detail::disable_overload_if_t::value && std::is_move_assignable::value,optional&&> other) = delete; + + /// \brief Perfect-forwarded assignment + /// + /// Depending on whether *this contains a value before the call, the + /// contained value is either direct-initialized from std::forward(value) + /// or assigned from std::forward(value). + /// + /// \note The function does not participate in overload resolution unless + /// - decay_t is not optional, + /// - std::is_constructible_v is true + /// - std::is_assignable_v is true + /// - and at least one of the following is true: + /// - T is not a scalar type; + /// - decay_t is not T. + /// + /// \param value to assign to the contained value + /// \return reference to \c (*this) + template ::value>> + optional& operator=(U&& value); + + /// \brief Assigns the state of \p other + /// + /// If both *this and other do not contain a value, the function has no effect. + /// + /// If *this contains a value, but other does not, then the contained + /// value is destroyed by calling its destructor. *this does not + /// contain a value after the call. + /// + /// If other contains a value, then depending on whether *this contains a value, + /// the contained value is either direct-initialized or assigned from *other. + /// + /// \note A moved-from optional still contains a value. + /// + /// \note This overload does not participate in overload resolution unless the + /// following conditions are met: + /// - std::is_constructible_v and + /// std::is_assignable_v are both true. + /// - T is not constructible, convertible, or assignable from any expression + /// of type (possibly const) :optional, i.e., + /// the following 12 type traits are all false: + /// - std::is_constructible_v&> + /// - std::is_constructible_v&> + /// - std::is_constructible_v&&> + /// - std::is_constructible_v&&> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_assignable_v&> + /// - std::is_assignable_v&> + /// - std::is_assignable_v&&> + /// - std::is_assignable_v&&>. + /// + /// \param other another optional object whose contained value to assign + /// \return reference to (*this) + template + optional& operator=(enable_if_t::value,const optional&> other); + + /// \brief Assigns the state of \p other + /// + /// If both *this and other do not contain a value, the function has no effect. + /// + /// If *this contains a value, but other does not, then the contained + /// value is destroyed by calling its destructor. *this does not + /// contain a value after the call. + /// + /// If other contains a value, then depending on whether *this contains a value, + /// the contained value is either direct-initialized or assigned from + /// std::move(*other). + /// + /// \note A moved-from optional still contains a value. + /// + /// \note This overload does not participate in overload resolution unless the + /// following conditions are met: + /// - std::is_constructible_v and + /// std::is_assignable_v are both true. + /// - T is not constructible, convertible, or assignable from any expression + /// of type (possibly const) :optional, i.e., + /// the following 12 type traits are all false: + /// - std::is_constructible_v&> + /// - std::is_constructible_v&> + /// - std::is_constructible_v&&> + /// - std::is_constructible_v&&> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_convertible_v&&, T> + /// - std::is_assignable_v&> + /// - std::is_assignable_v&> + /// - std::is_assignable_v&&> + /// - std::is_assignable_v&&>. + /// + /// \param other another optional object whose contained value to assign + /// \return reference to (*this) + template + optional& operator=(enable_if_t::value,optional&&> other); + + //----------------------------------------------------------------------- + // Observers + //----------------------------------------------------------------------- + + /// \{ + /// \brief Accesses the contained value + /// + /// \note The behavior is undefined if \c *this does not contain a value. + /// + /// \return a pointer to the contained value + BPSTD_CPP14_CONSTEXPR value_type* operator->() noexcept; + constexpr const value_type* operator->() const noexcept; + /// \} + + /// \{ + /// \brief Accesses the contained value + /// + /// \note The behaviour is undefined if \c *this does not contain a value + /// + /// \return a reference to the contained value + BPSTD_CPP14_CONSTEXPR value_type& operator*() & noexcept; + BPSTD_CPP14_CONSTEXPR value_type&& operator*() && noexcept; + constexpr const value_type& operator*() const& noexcept; + constexpr const value_type&& operator*() const&& noexcept; + /// \} + + /// \brief Checks whether \c *this contains a value + /// + /// \return \c true if \c *this contains a value, \c false if \c *this + /// does not contain a value + constexpr explicit operator bool() const noexcept; + + /// \brief Checks whether \c *this contains a value + /// + /// \return \c true if \c *this contains a value, \c false if \c *this + /// does not contain a value + constexpr bool has_value() const noexcept; + + //----------------------------------------------------------------------- + + /// \{ + /// \brief Returns the contained value. + /// + /// \throws bad_optional_access if \c *this does not contain a value. + /// + /// \return the value of \c *this + BPSTD_CPP14_CONSTEXPR value_type& value() &; + BPSTD_CPP14_CONSTEXPR value_type&& value() &&; + /// \} + + /// \{ + /// \brief Returns the contained value. + /// + /// \throws bad_optional_access if \c *this does not contain a value. + /// + /// \return the value of \c *this + BPSTD_CPP14_CONSTEXPR const value_type& value() const &; + BPSTD_CPP14_CONSTEXPR const value_type&& value() const &&; + /// \} + + //----------------------------------------------------------------------- + + /// \{ + /// \brief Returns the contained value if \c *this has a value, + /// otherwise returns \p default_value. + /// + /// \param default_value the value to use in case \c *this is empty + /// \return the value to use in case \c *this is empty + template + constexpr value_type value_or(U&& default_value) const &; + template + BPSTD_CPP14_CONSTEXPR value_type value_or(U&& default_value) &&; + /// \} + + //----------------------------------------------------------------------- + // Modifiers + //----------------------------------------------------------------------- + + /// \brief Swaps the contents with those of other. + /// + /// \param other the optional object to exchange the contents with + void swap(optional& other); + + /// \brief If \c *this contains a value, destroy that value as if by + /// \c value().T::~T(). + /// + /// Otherwise, there are no effects. \c *this does not contain a value + /// after this call. + void reset() noexcept(std::is_nothrow_destructible::value); + + /// \brief Constructs the contained value in-place. + /// + /// If \c *this already contains a value before the call, the contained + /// value is destroyed by calling its destructor. + /// + /// \param args the arguments to pass to the constructor + template + void emplace(Args&&...args); + + /// \brief Constructs the contained value in-place. + /// + /// If \c *this already contains a value before the call, the contained + /// value is destroyed by calling its destructor. + /// + /// \param ilist the initializer list to pass to the constructor + /// \param args the arguments to pass to the constructor + template + void emplace(std::initializer_list ilist, Args&&...args); + }; + + //========================================================================= + // non-member functions : class : optional + //========================================================================= + + //------------------------------------------------------------------------- + // Comparison + //------------------------------------------------------------------------- + + template + BPSTD_CPP14_CONSTEXPR bool operator==(const optional& lhs, const optional& rhs); + template + BPSTD_CPP14_CONSTEXPR bool operator!=(const optional& lhs, const optional& rhs); + template + BPSTD_CPP14_CONSTEXPR bool operator<(const optional& lhs, const optional& rhs); + template + BPSTD_CPP14_CONSTEXPR bool operator>(const optional& lhs, const optional& rhs); + template + BPSTD_CPP14_CONSTEXPR bool operator<=(const optional& lhs, const optional& rhs); + template + BPSTD_CPP14_CONSTEXPR bool operator>=(const optional& lhs, const optional& rhs); + + //------------------------------------------------------------------------- + + template + constexpr bool operator==(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator==(nullopt_t, const optional& opt) noexcept; + template + constexpr bool operator!=(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator!=(nullopt_t, const optional& opt) noexcept; + template + constexpr bool operator<(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator<(nullopt_t, const optional& opt) noexcept; + template + constexpr bool operator>(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator>(nullopt_t, const optional& opt) noexcept; + template + constexpr bool operator<=(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator<=(nullopt_t, const optional& opt) noexcept; + template + constexpr bool operator>=(const optional& opt, nullopt_t) noexcept; + template + constexpr bool operator>=(nullopt_t, const optional& opt) noexcept; + + //------------------------------------------------------------------------- + + template + constexpr bool operator==(const optional& opt, const T& value); + template + constexpr bool operator==(const T& value, const optional& opt); + template + constexpr bool operator!=(const optional& opt, const T& value); + template + constexpr bool operator!=(const T& value, const optional& opt); + template + constexpr bool operator<(const optional& opt, const T& value); + template + constexpr bool operator<(const T& value, const optional& opt); + template + constexpr bool operator>(const optional& opt, const T& value); + template + constexpr bool operator>(const T& value, const optional& opt); + template + constexpr bool operator<=(const optional& opt, const T& value); + template + constexpr bool operator<=(const T& value, const optional& opt); + template + constexpr bool operator>=(const optional& opt, const T& value); + template + constexpr bool operator>=(const T& value, const optional& opt); + + //------------------------------------------------------------------------- + // Utilities + //------------------------------------------------------------------------- + + /// \brief Creates an optional object from \p value + /// + /// \param value the value to construct the optional from + template + constexpr optional> make_optional(T&& value); + + /// \brief Creates an optional object of type \p T from the given \p args + /// + /// \tparam T the type to construct + /// \param args the arguments to pass to \p T's constructor + template + constexpr optional make_optional(Args&&... args); + + /// \brief Creates an optional object of type \p T from the given + /// \p il \p args + /// + /// \tparam T the type to construct + /// \param il the initializer list to pass + /// \param args the arguments to pass to \p T's constructor + template + constexpr optional make_optional(std::initializer_list il, Args&&... args); + + //------------------------------------------------------------------------- + + /// \brief Swaps \p lhs and \p rhs + /// + /// \param lhs the left optional to swap + /// \param rhs the right optional to swap + template + void swap(optional& lhs, optional& rhs); + +} // namespace bpstd + +//============================================================================= +// class : detail::optional_base +//============================================================================= + +//----------------------------------------------------------------------------- +// Constructors +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::optional_base + ::optional_base(nullopt_t) + noexcept + : m_storage{}, + m_engaged{false} +{ +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::optional_base::optional_base(in_place_t, Args&&...args) + noexcept(std::is_nothrow_constructible::value) + : m_storage(in_place, bpstd::forward(args)...), + m_engaged{true} +{ + +} + +//----------------------------------------------------------------------------- +// Protected Observers +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T* bpstd::detail::optional_base::val() + noexcept +{ + return &m_storage.something; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const T* bpstd::detail::optional_base::val() + const noexcept +{ + return &m_storage.something; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::detail::optional_base::contains_value() + const noexcept +{ + return m_engaged; +} + +//----------------------------------------------------------------------------- +// Protected Modifiers +//----------------------------------------------------------------------------- + +template +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::optional_base::construct(Args&&...args) +{ + m_storage.something = T(bpstd::forward(args)...); + m_engaged = true; +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::optional_base::destruct() +{ + m_engaged = false; +} + +//============================================================================= +// class : detail::optional_base +//============================================================================= + +//----------------------------------------------------------------------------- +// Constructors / Destructor +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::detail::optional_base + ::optional_base(nullopt_t) + noexcept + : m_storage{}, + m_engaged{false} +{ +} + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::detail::optional_base + ::optional_base(in_place_t, Args&&...args) + noexcept(std::is_nothrow_constructible::value) + : m_storage(in_place, bpstd::forward(args)...), + m_engaged{true} +{ + +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::detail::optional_base::~optional_base() + noexcept(std::is_nothrow_destructible::value) +{ + if (m_engaged) { + m_storage.something.~T(); + } +} + +//----------------------------------------------------------------------------- +// Protected Observers +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +T* bpstd::detail::optional_base::val() + noexcept +{ + return &m_storage.something; +} + +template +inline BPSTD_INLINE_VISIBILITY +const T* bpstd::detail::optional_base::val() + const noexcept +{ + return &m_storage.something; +} + +template +inline BPSTD_INLINE_VISIBILITY +bool bpstd::detail::optional_base::contains_value() + const noexcept +{ + return m_engaged; +} + +//----------------------------------------------------------------------------- +// Protected Modifiers +//----------------------------------------------------------------------------- + +template +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::optional_base::construct(Args&&...args) +{ + new (&m_storage.something) T(bpstd::forward(args)...); + m_engaged = true; +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::detail::optional_base::destruct() +{ + if (m_engaged) { + m_storage.something.~T(); + m_engaged = false; + } +} + +//============================================================================= +// class : optional +//============================================================================= + +//----------------------------------------------------------------------------- +// Constructor / Assignment +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::optional() + noexcept + : base_type{ nullopt } +{ + +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::optional(nullopt_t) + noexcept + : optional{} +{ + +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional + ::optional(detail::enable_overload_if_t::value,const optional&> other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(*other); + } +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional + ::optional(detail::enable_overload_if_t::value,optional&&> other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(bpstd::move(*other)); + } +} + +//----------------------------------------------------------------------------- + +template +template ::value && std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY +bpstd::optional::optional(const optional& other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(*other); + } +} + +template +template ::value && !std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY +bpstd::optional::optional(const optional& other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(*other); + } +} + +//----------------------------------------------------------------------------- + +template +template ::value && std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY +bpstd::optional::optional(optional&& other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(bpstd::move(*other)); + } +} +template +template ::value && !std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY +bpstd::optional::optional(optional&& other) + : optional{} +{ + if (other.has_value()) + { + base_type::construct(bpstd::move(*other)); + } +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::optional(in_place_t, Args&&...args) + : base_type{ in_place, bpstd::forward(args)... } +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional + ::optional( in_place_t, + std::initializer_list ilist, + Args&&...args ) + : base_type{ in_place, ilist, bpstd::forward(args)... } +{ + +} + +template +template ::value && std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::optional(U&& value) + : base_type{ in_place, bpstd::forward(value) } +{ + +} + +template +template ::value && !std::is_convertible::value>*> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::optional(U&& value) + : base_type{ in_place, bpstd::forward(value) } +{ + +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional& bpstd::optional::operator=(nullopt_t) +{ + base_type::destruct(); + return (*this); +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional& + bpstd::optional::operator=(detail::enable_overload_if_t::value && std::is_copy_assignable::value,const optional&> other) +{ + if (has_value() && other.has_value()) { + (*base_type::val()) = (*other); + } else if (has_value()) { + base_type::destruct(); + } else if (other.has_value()) { + base_type::construct(*other); + } + + return (*this); +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional& + bpstd::optional::operator=(detail::enable_overload_if_t::value && std::is_move_assignable::value,optional&&> other) +{ + if (has_value() && other.has_value()) { + (*base_type::val()) = bpstd::move(*other); + } else if (has_value()) { + base_type::destruct(); + } else if (other.has_value()) { + base_type::construct(bpstd::move( *other )); + } + + return (*this); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::optional& bpstd::optional::operator=(U&& value) +{ + if (has_value()) { + (*base_type::val()) = bpstd::forward(value); + } else { + base_type::construct(bpstd::forward(value)); + } + return (*this); +} + +//----------------------------------------------------------------------------- +// Observers +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional::operator bool() + const noexcept +{ + return base_type::contains_value(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::optional::has_value() + const noexcept +{ + return base_type::contains_value(); +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type* + bpstd::optional::operator->() + noexcept +{ + return base_type::val(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const typename bpstd::optional::value_type* + bpstd::optional::operator->() + const noexcept +{ + return base_type::val(); +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type& + bpstd::optional::operator*() + & noexcept +{ + return *base_type::val(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type&& + bpstd::optional::operator*() + && noexcept +{ + return bpstd::move(*base_type::val()); +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const typename bpstd::optional::value_type& + bpstd::optional::operator*() + const & noexcept +{ + return *base_type::val(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const typename bpstd::optional::value_type&& + bpstd::optional::operator*() + const && noexcept +{ + return bpstd::move(*base_type::val()); +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type& + bpstd::optional::value() + & +{ + if (static_cast(*this)) { + return *base_type::val(); + } + throw bad_optional_access{}; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type&& + bpstd::optional::value() + && +{ + if (static_cast(*this)) { + return bpstd::move(*base_type::val()); + } + throw bad_optional_access{}; +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const typename bpstd::optional::value_type& + bpstd::optional::value() + const & +{ + if (static_cast(*this)) { + return *base_type::val(); + } + throw bad_optional_access{}; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const typename bpstd::optional::value_type&& + bpstd::optional::value() + const && +{ + if (static_cast(*this)) { + return bpstd::move(*base_type::val()); + } + throw bad_optional_access{}; +} + +//----------------------------------------------------------------------------- + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::optional::value_type + bpstd::optional::value_or(U&& default_value) + const & +{ + return bool(*this) ? (*base_type::val()) : bpstd::forward(default_value); +} + +template +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::optional::value_type + bpstd::optional::value_or(U&& default_value) + && +{ + return bool(*this) ? (*base_type::val()) : bpstd::forward(default_value); +} + +//----------------------------------------------------------------------------- +// Modifiers +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::optional::swap(optional& other) +{ + using std::swap; + + if (has_value() && other.has_value()){ + swap(*base_type::val(), *other); + } else if (has_value()) { + other = bpstd::move(*this); + reset(); // leave this unengaged + } else if (other.has_value()) { + *this = bpstd::move(other); + other.reset(); // leave 'other' unengaged + } +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::optional::reset() + noexcept(std::is_nothrow_destructible::value) +{ + base_type::destruct(); +} + +//----------------------------------------------------------------------------- + +template +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::optional::emplace(Args&&...args) +{ + base_type::destruct(); + base_type::construct(bpstd::forward(args)...); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::optional::emplace(std::initializer_list ilist, + Args&&...args) +{ + base_type::destruct(); + base_type::construct(ilist, bpstd::forward(args)...); +} + +//============================================================================= +// Equality Operators +//============================================================================= + +//----------------------------------------------------------------------------- +// Comparison +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator==(const optional& lhs, const optional& rhs) +{ + if (static_cast(lhs) != static_cast(rhs)) { + return false; + } + if (!static_cast(lhs)) { + return true; + } + return *lhs == *rhs; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator!=(const optional& lhs, const optional& rhs) +{ + if (static_cast(lhs) != static_cast(rhs)) { + return true; + } + if (!static_cast(lhs)) { + return false; + } + return *lhs != *rhs; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator<(const optional& lhs, const optional& rhs) +{ + if (!static_cast(rhs)) { + return false; + } + if (!static_cast(lhs)) { + return true; + } + return *lhs < *rhs; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator>(const optional& lhs, const optional& rhs) +{ + if (!static_cast(lhs)) { + return false; + } + if (!static_cast(rhs)) { + return true; + } + return *lhs > *rhs; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator<=(const optional& lhs, const optional& rhs) +{ + if (!static_cast(lhs)) { + return true; + } + if (!static_cast(rhs)) { + return false; + } + return *lhs <= *rhs; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool + bpstd::operator>=(const optional& lhs, const optional& rhs) +{ + if (!static_cast(rhs)) { + return true; + } + if (!static_cast(lhs)) { + return false; + } + return *lhs >= *rhs; +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator==(const optional& opt, nullopt_t) + noexcept +{ + return !opt; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator==(nullopt_t, const optional& opt) + noexcept +{ + return !opt; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator!=(const optional& opt, nullopt_t) + noexcept +{ + return static_cast(opt); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator!=(nullopt_t, const optional& opt) + noexcept +{ + return static_cast(opt); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<(const optional&, nullopt_t) + noexcept +{ + return false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<(nullopt_t, const optional& opt) + noexcept +{ + return static_cast(opt); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>(const optional& opt, nullopt_t) + noexcept +{ + return static_cast(opt); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>(nullopt_t, const optional&) + noexcept +{ + return false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<=(const optional& opt, nullopt_t) + noexcept +{ + return !opt; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<=(nullopt_t, const optional&) + noexcept +{ + return true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>=(const optional&, nullopt_t) + noexcept +{ + return true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>=(nullopt_t, const optional& opt) + noexcept +{ + return !opt; +} + +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator==(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt == value : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator==(const T& value, const optional& opt) +{ + return static_cast(opt) ? value == *opt : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator!=(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt != value : true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator!=(const T& value, const optional& opt) +{ + return static_cast(opt) ? value != *opt : true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt < value : true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<(const T& value, const optional& opt) +{ + return static_cast(opt) ? value < *opt : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt > value : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>(const T& value, const optional& opt) +{ + return static_cast(opt) ? value > *opt : true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<=(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt <= value : true; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<=(const T& value, const optional& opt) +{ + return static_cast(opt) ? value <= *opt : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>=(const optional& opt, const T& value) +{ + return static_cast(opt) ? *opt >= value : false; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>=(const T& value, const optional& opt) +{ + return static_cast(opt) ? value >= *opt : true; +} + +//----------------------------------------------------------------------------- +// Non-member functions +//----------------------------------------------------------------------------- + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional> bpstd::make_optional(T&& value) +{ + return optional>(bpstd::forward(value)); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional bpstd::make_optional(Args&&... args) +{ + return optional(in_place, bpstd::forward(args)...); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::optional bpstd::make_optional(std::initializer_list il, Args&&... args) +{ + return optional( + in_place, + std::forward>(il), + std::forward(args)... + ); +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::swap(optional& lhs, optional& rhs) +{ + lhs.swap(rhs); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_OPTIONAL_HPP */ diff --git a/src/libs/vmisc/bpstd/span.hpp b/src/libs/vmisc/bpstd/span.hpp new file mode 100644 index 000000000..e0d253be7 --- /dev/null +++ b/src/libs/vmisc/bpstd/span.hpp @@ -0,0 +1,806 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file span.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_SPAN_HPP +#define BPSTD_SPAN_HPP + +#include "detail/config.hpp" +#include "detail/proxy_iterator.hpp" + +#include "cstddef.hpp" // byte +#include "memory.hpp" // to_address +#include "type_traits.hpp" // conjunction, remove_cvref_t, etc + +#include // std::size_t +#include // std::array +#include // std::iterator_traits + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // constants : dynamic_extent + //============================================================================ + + BPSTD_CPP17_INLINE constexpr auto dynamic_extent = static_cast(-1); + + namespace detail { + + template + class extent_storage + { + public: + constexpr extent_storage() noexcept = default; + + template + constexpr explicit extent_storage(extent_storage) + { + static_assert( + UExtent == Extent, + "Extent must be the same size as UExtent" + ); + } + + constexpr explicit extent_storage(std::size_t) + { + + } + + constexpr std::size_t size() const noexcept + { + return Extent; + } + }; + + template <> + class extent_storage + { + public: + template + constexpr explicit extent_storage(extent_storage ext) + : m_size{ext.size()} + { + + } + + constexpr explicit extent_storage(std::size_t size) + : m_size{size} + { + + } + + constexpr std::size_t size() const noexcept + { + return m_size; + } + + private: + + std::size_t m_size; + }; + + template + class span_storage_type : public extent_storage + { + //------------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------------ + public: + + template + constexpr span_storage_type(T* data, ExtentType ext) + : extent_storage(ext), + m_data{data} + { + + } + + //------------------------------------------------------------------------ + // Observers + //------------------------------------------------------------------------ + public: + + using extent_storage::size; + + constexpr T* data() const noexcept { return m_data; } + + //------------------------------------------------------------------------ + // Private Members + //------------------------------------------------------------------------ + private: + + T* m_data; + }; + + template + struct is_allowed_extent_conversion + : bool_constant<(From == To) || (To == dynamic_extent)>{}; + + template + struct compute_subspan_size + : integral_constant{}; + + template + using iter_reference = typename std::iterator_traits::reference; + + template + using is_iter_convertible = conjunction< + is_same>,remove_cv_t>, + is_convertible,remove_cv_t> + >; + + } // namespace detail + + //============================================================================ + // class : span + //============================================================================ + + ////////////////////////////////////////////////////////////////////////////// + /// \brief This class is a non-owning view of a contiguous piece of memory + /// + /// This type describes an object that can refer to a contiguous sequence of + /// objects with the first element of the sequence at position zero. A span + /// can either have a static extent, in which case the number of elements in + /// the sequence is known and encoded in the type, or a dynamic extent, + /// in which case the size is known at runtime. + /// + /// \tparam T the underlying type of the span + /// \tparam Extent the extent (size) of the span + ////////////////////////////////////////////////////////////////////////////// + template + class span + { + //-------------------------------------------------------------------------- + // Public Member Types + //-------------------------------------------------------------------------- + public: + + using element_type = T; + using value_type = remove_cv_t; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + + using iterator = detail::proxy_iterator>; + using reverse_iterator = std::reverse_iterator; + + //-------------------------------------------------------------------------- + // Public Member Constants + //-------------------------------------------------------------------------- + public: + + BPSTD_CPP17_INLINE static constexpr std::size_t extent = Extent; + + //-------------------------------------------------------------------------- + // Constructors / Assignment + //-------------------------------------------------------------------------- + public: + + /// \brief Default-constructs a span + /// + /// This constructor only participates in overload resolution if the span + /// either is size 0, or has a dynamic extent + template ::value>> + constexpr span() noexcept; + + /// \{ + /// \brief Constructs a span from an iterator \p it and the \p count + /// + /// This constructor only participates in overload resolution if the + /// following criteria are met: + /// * Extent is dynamic_extent + /// * to_address(it) is convertible to T* + /// + /// This constructor is explicit if `Extent` != `dynamic_extent` + /// + /// \param it the iterator + /// \param count the number of entries in the sequence + template ::value,int> = 0> + constexpr span(It it, size_type count) noexcept; + template ::value,int> = 0> + constexpr explicit span(It it, size_type count) noexcept; + /// \} + + /// \brief Constructs a span from an iterator range + /// + /// This constructor only participates in overload resolution if the + /// following criteria are met: + /// * Extent is dynamic_extent + /// * to_address(it) is convertible to T* + /// + /// \param it the iterator + /// \param end the end iterator + template ::value, int> = 0> + constexpr span(It it, End end) noexcept; + template ::value, int> = 0> + constexpr explicit span(It it, End end) noexcept; + + /// \brief Constructs a span from an array reference + /// + /// This constructor only participates in overload resolution if any of the + /// following criteria are met: + /// * Extent is dynamic_extent + /// * N is the same as Extent + /// + /// \param arr the array reference + template ::value>> + // cppcheck-suppress noExplicitConstructor + constexpr span(element_type (&arr)[N]) noexcept; + + /// \{ + /// \brief Constructs a span from a reference to a std::array + /// + /// This constructor only participates in overload resolution if the + /// following criteria are met: + /// * Extent is dynamic_extent or N is the same as Extent + /// * U is at most a cv-qualification difference from T + /// + /// \param arr the array reference + template ::value>> + // cppcheck-suppress noExplicitConstructor + constexpr span(std::array& arr) noexcept; + template ::value>> + // cppcheck-suppress noExplicitConstructor + constexpr span(const std::array& arr) noexcept; + /// \} + + // range-constructor omitted since ranges are not part of backport yet + + /// \brief Constructs a span from a different span + /// + /// This constructor only participates in overload resolution if the + /// following criteria are met: + /// * Extent is dynamic_extent or N is the same as Extent + /// * U is at most a cv-qualification difference from T + /// + /// \param s the span + template ::value>> + // cppcheck-suppress noExplicitConstructor + constexpr span(const span& s) noexcept; + + /// \brief Constructs a span by copying \p other + /// + /// \param other the other span to copy + constexpr span(const span& other) noexcept = default; + + //-------------------------------------------------------------------------- + + /// \brief Assigns a span from \p other + /// + /// \param other the other span to copy + /// \return reference to this + BPSTD_CPP14_CONSTEXPR span& operator=(const span& other) noexcept = default; + + //-------------------------------------------------------------------------- + // Element Access + //-------------------------------------------------------------------------- + public: + + /// \brief Gets a reference to the front element of this span + /// + /// \pre empty() is false + /// \return reference to front element + constexpr reference front() const noexcept; + + /// \brief Gets a reference to the back element of this span + /// + /// \pre empty() is false + /// \return reference to back element + constexpr reference back() const noexcept; + + /// \brief Gets a reference to the element at \p idx + /// + /// \pre \p idx is less than size() + /// \param idx the index + /// \return reference to the element at \p idx + constexpr reference operator[](size_type idx) const noexcept; + + /// \brief Gets a pointer to the start of the data + /// + /// \return pointer to the data + constexpr pointer data() const noexcept; + + //-------------------------------------------------------------------------- + // Observers + //-------------------------------------------------------------------------- + public: + + /// \brief Gets the number of elements in this span + /// + /// \return the number of elements in this span + constexpr size_type size() const noexcept; + + /// \brief Gets the number of bytes in this span + /// + /// \return the number of bytes in this span + constexpr size_type size_bytes() const noexcept; + + /// \brief Queries whether this span is empty + /// + /// \return true if this span is empty + constexpr bool empty() const noexcept; + + //-------------------------------------------------------------------------- + // Subviews + //-------------------------------------------------------------------------- + public: + + /// \brief Creates a subspan from the first \p Count elements + /// + /// \pre A program is ill-formed if \p Count > Extent + /// + /// \tparam Count the number of elements to create in the subspan + /// \return the first \p Count elements + template + constexpr span first() const; + + /// \brief Creates a subspan from the first \p count elements + /// + /// \pre It is undefined behavior if \p count > size() + /// + /// \param count the number of elements to create in the subspan + /// \return the first \p count elements + constexpr span first(size_t count) const; + + //-------------------------------------------------------------------------- + + /// \brief Creates a subspan from the last \p Count elements + /// + /// \pre A program is ill-formed if \p Count > Extent + /// + /// \tparam Count the number of elements to create in the subspan + /// \return the last \p Count elements + template + constexpr span last() const; + + /// \brief Creates a subspan from the last \p count elements + /// + /// \pre It is undefined behavior if \p count > size() + /// + /// \param count the number of elements to create in the subspan + /// \return the last \p count elements + constexpr span last(size_t count) const; + + //-------------------------------------------------------------------------- + + /// \brief Creates a subspan that is \p Count elements long, \p Offset from + /// the start of this span + /// + /// \tparam Offset the amount to offset the span by + /// \tparam Count the number of elements to create in the subspan + /// \return the created subspan + template + constexpr span::value> + subspan() const; + + /// \brief Creates a subspan that is \p count elements long, \p offset from + /// the start of this span + /// + /// \param offset the amount to offset the span by + /// \param count the number of elements to create in the subspan + /// \return the created subspan + constexpr span subspan(std::size_t offset, + std::size_t count = dynamic_extent) const; + + //-------------------------------------------------------------------------- + // Iterators + //-------------------------------------------------------------------------- + public: + + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + + //-------------------------------------------------------------------------- + // Private Members + //-------------------------------------------------------------------------- + private: + + using storage_type = detail::span_storage_type; + + storage_type m_storage; + }; + + //============================================================================ + // non-member functions : class : span + //============================================================================ + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + /// \brief Converts a span \p s to a byte span + /// + /// \param s the span to convert + /// \return a span of the byte range that \p s covered + template + span as_bytes(span s) noexcept; + + /// \brief Converts a span \p s to a writable byte span + /// + /// \param s the span to convert + /// \return a span of the byte range that \p s covered + template + span as_writable_bytes(span s) noexcept; + +} // namespace bpstd + +template +constexpr std::size_t bpstd::span::extent; + +//============================================================================== +// non-member functions : class : span +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span() + noexcept + : m_storage{nullptr, detail::extent_storage<0>{}} +{ + +} + +template +template ::value,int>> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(It it, size_type count) + noexcept + : m_storage{to_address(it), count} +{ + +} + +template +template ::value,int>> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(It it, size_type count) + noexcept + : m_storage{to_address(it), count} +{ + +} + +template +template ::value, int>> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(It it, End end) + noexcept + : m_storage{to_address(it), static_cast(end - it)} +{ + +} + +template +template ::value, int>> +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(It it, End end) + noexcept + : m_storage{to_address(it), static_cast(end - it)} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(element_type (&arr)[N]) + noexcept + : m_storage{static_cast(arr), detail::extent_storage{}} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(std::array& arr) + noexcept + : m_storage{arr.data(), detail::extent_storage{}} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(const std::array& arr) + noexcept + : m_storage{arr.data(), detail::extent_storage{}} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::span(const span& s) + noexcept + : m_storage{s.data(), detail::extent_storage{s.size()}} +{ + +} + +//------------------------------------------------------------------------------ +// Element Access +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::reference + bpstd::span::front() + const noexcept +{ + return data()[0]; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::reference + bpstd::span::back() + const noexcept +{ + return data()[m_storage.size()-1]; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::reference + bpstd::span::operator[](size_type idx) + const noexcept +{ + return data()[idx]; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::pointer + bpstd::span::data() + const noexcept +{ + return m_storage.data(); +} + +//------------------------------------------------------------------------------ +// Observers +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::size_type + bpstd::span::size() + const noexcept +{ + return m_storage.size(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::size_type + bpstd::span::size_bytes() + const noexcept +{ + return size() * sizeof(T); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::span::empty() + const noexcept +{ + return size() == 0u; +} + +//------------------------------------------------------------------------------ +// Subviews +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type, Count> + bpstd::span::first() + const +{ + static_assert( + Count <= Extent, + "A Count larger than Extent is ill-formed" + ); + + return span{data(), Count}; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type> + bpstd::span::first(size_t count) + const +{ + return {data(), count}; +} + +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type, Count> + bpstd::span::last() + const +{ + static_assert( + Count <= Extent, + "A Count larger than Extent is ill-formed" + ); + + return span{data() + (size() - Count), Count}; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type> + bpstd::span::last(size_t count) + const +{ + return {data() + (size() - count), count}; +} + +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type, bpstd::detail::compute_subspan_size::value> + bpstd::span::subspan() + const +{ + using result_type = span< + element_type, + detail::compute_subspan_size::value + >; + + return result_type{ + data() + Offset, + (Count == dynamic_extent) ? (size() - Offset) : Count + }; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::span::element_type> + bpstd::span::subspan(std::size_t offset, std::size_t count) + const +{ + return { + data() + offset, + (count == dynamic_extent) ? (size() - offset) : count + }; +} + +//------------------------------------------------------------------------------ +// Iterators +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::iterator + bpstd::span::begin() + const noexcept +{ + return iterator{data()}; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::iterator + bpstd::span::end() + const noexcept +{ + return iterator{data() + size()}; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::reverse_iterator + bpstd::span::rbegin() + const noexcept +{ + return reverse_iterator(end()); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::span::reverse_iterator + bpstd::span::rend() + const noexcept +{ + return reverse_iterator(begin()); +} + +//============================================================================== +// non-member functions : class : span +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline bpstd::span bpstd::as_bytes(span s) + noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +template +inline bpstd::span bpstd::as_writable_bytes(span s) + noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_SPAN_HPP */ diff --git a/src/libs/vmisc/bpstd/string.hpp b/src/libs/vmisc/bpstd/string.hpp new file mode 100644 index 000000000..20f004c88 --- /dev/null +++ b/src/libs/vmisc/bpstd/string.hpp @@ -0,0 +1,84 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file string.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_STRING_HPP +#define BPSTD_STRING_HPP + +#include "detail/config.hpp" + +#include + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + inline namespace literals { + inline namespace string_literals { + + std::string operator""_s(const char* s, std::size_t len); + std::u16string operator""_s(const char16_t* s, std::size_t len); + std::u32string operator""_s(const char32_t* s, std::size_t len); + std::wstring operator""_s(const wchar_t* s, std::size_t len); + + } // inline namespace string_literals + } // inline namespace literals + +} // namespace bpstd + +inline BPSTD_INLINE_VISIBILITY +std::string + bpstd::literals::string_literals::operator""_s(const char* s, std::size_t len) +{ + return std::string{s, len}; +} + +inline BPSTD_INLINE_VISIBILITY +std::u16string + bpstd::literals::string_literals::operator""_s(const char16_t* s, std::size_t len) +{ + return std::u16string{s, len}; +} + +inline BPSTD_INLINE_VISIBILITY +std::u32string + bpstd::literals::string_literals::operator""_s(const char32_t* s, std::size_t len) +{ + return std::u32string{s, len}; +} + +inline BPSTD_INLINE_VISIBILITY +std::wstring + bpstd::literals::string_literals::operator""_s(const wchar_t* s, std::size_t len) +{ + return std::wstring{s, len}; +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_STRING_HPP */ diff --git a/src/libs/vmisc/bpstd/string_view.hpp b/src/libs/vmisc/bpstd/string_view.hpp new file mode 100644 index 000000000..0066fbfe6 --- /dev/null +++ b/src/libs/vmisc/bpstd/string_view.hpp @@ -0,0 +1,1529 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file string_view.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2016 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_STRING_VIEW_HPP +#define BPSTD_STRING_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" // BPSTD_CPP14_CONSTEXPR + +#include // std::min, std::max +#include // std::char_traits +#include // std::basic_ostream +#include // std::size_t +#include // std::allocator +#include // std::out_of_range +#include // std::reverse_iterator +#include // std::streamsize + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { // back-port std + + ////////////////////////////////////////////////////////////////////////////// + /// \brief A semantic non-owning wrapper around contiguous character + /// sequences. + /// + /// This class describes an object that can refer to a constant contiguous + /// sequence of char-like objects with the first element of the sequence + /// at position zero. + ////////////////////////////////////////////////////////////////////////////// + template > + class basic_string_view + { + //-------------------------------------------------------------------------- + // Public Member Types + //-------------------------------------------------------------------------- + public: + + using char_type = CharT; + using traits_type = Traits; + using size_type = std::size_t; + + using value_type = CharT; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + + using iterator = const CharT*; + using const_iterator = const CharT*; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + //-------------------------------------------------------------------------- + // Public Members + //-------------------------------------------------------------------------- + public: + + static constexpr size_type npos = size_type(-1); + + //-------------------------------------------------------------------------- + // Constructors + //-------------------------------------------------------------------------- + public: + + /// \brief Default constructs a basic_string_view without any content + constexpr basic_string_view() noexcept; + + /// \brief Constructs a basic_string_view by copying another one + /// + /// \param other the string view being copied + constexpr basic_string_view(const basic_string_view& other) noexcept = default; + + /// \brief Constructs a basic_string_view by moving anothe rone + /// + /// \param other the string view being moved + constexpr basic_string_view(basic_string_view&& other) noexcept = default; + + /// \brief Constructs a basic_string_view from a std::basic_string + /// + /// \param str the string to view + template + // cppcheck-suppress noExplicitConstructor + basic_string_view(const std::basic_string& str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi-string + /// + /// \param str the string to view + // cppcheck-suppress noExplicitConstructor + constexpr basic_string_view(const char_type* str) noexcept; + + /// \brief Constructs a basic_string_view from an ansi string of a given size + /// + /// \param str the string to view + /// \param count the size of the string + constexpr basic_string_view(const char_type* str, size_type count) noexcept; + + //-------------------------------------------------------------------------- + // Assignment + //-------------------------------------------------------------------------- + public: + + /// \brief Assigns a basic_string_view from an ansi-string + /// + /// \param view the string to view + /// \return reference to \c (*this) + basic_string_view& operator=(const basic_string_view& view) = default; + + //-------------------------------------------------------------------------- + // Capacity + //-------------------------------------------------------------------------- + public: + + /// \{ + /// \brief Returns the length of the string, in terms of bytes + /// + /// \return the length of the string, in terms of bytes + constexpr size_type size() const noexcept; + constexpr size_type length() const noexcept; + /// \} + + /// \brief The largest possible number of char-like objects that can be + /// referred to by a basic_string_view. + /// \return Maximum number of characters + constexpr size_type max_size() const noexcept; + + /// \brief Returns whether the basic_string_view is empty + /// (i.e. whether its length is 0). + /// + /// \return whether the basic_string_view is empty + constexpr bool empty() const noexcept; + + //-------------------------------------------------------------------------- + // Element Access + //-------------------------------------------------------------------------- + public: + + /// \brief Gets the data of the current basic_string_view + /// + /// \note This is an alias of #c_str + /// + /// \return the data this basic_string_view contains + constexpr const char_type* data() const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference operator[](size_type pos) const noexcept; + + /// \brief Accesses the element at index \p pos + /// + /// \param pos the index to access + /// \return const reference to the character + constexpr const_reference at(size_type pos) const; + + /// \brief Access the first character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the first character of the string + constexpr const_reference front() const noexcept; + + /// \brief References the last character of the string + /// + /// \note Undefined behavior if basic_string_view is empty + /// + /// \return reference to the last character of the string + constexpr const_reference back() const noexcept; + + //-------------------------------------------------------------------------- + // Modifiers + //-------------------------------------------------------------------------- + public: + + /// \brief Moves the start of the view forward by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the start of the view + BPSTD_CPP14_CONSTEXPR void remove_prefix(size_type n) noexcept; + + /// \brief Moves the end of the view back by n characters. + /// + /// The behavior is undefined if n > size(). + /// + /// \param n number of characters to remove from the end of the view + BPSTD_CPP14_CONSTEXPR void remove_suffix(size_type n) noexcept; + + /// \brief Exchanges the view with that of v. + /// + /// \param v view to swap with + BPSTD_CPP14_CONSTEXPR void swap(basic_string_view& v) noexcept; + + //-------------------------------------------------------------------------- + // Conversions + //-------------------------------------------------------------------------- + public: + + /// \brief Creates a basic_string with a copy of the content of the current + /// view. + /// + /// \return A basic_string containing a copy of the characters of the + /// current view. + template + explicit constexpr operator std::basic_string() const; + + //-------------------------------------------------------------------------- + // Operations + //-------------------------------------------------------------------------- + public: + + /// \brief Copies the substring [pos, pos + rcount) to the character string pointed + /// to by dest, where rcount is the smaller of count and size() - pos. + /// + /// \param dest pointer to the destination character string + /// \param count requested substring length + /// \param pos position of the first character + BPSTD_CPP14_CONSTEXPR size_type copy(char_type* dest, + size_type count = npos, + size_type pos = 0) const; + + /// \brief Returns a substring of this viewed string + /// + /// \param pos the position of the first character in the substring + /// \param len the length of the substring + /// \return the created substring + BPSTD_CPP14_CONSTEXPR basic_string_view substr(size_t pos = 0, + size_t len = npos) const; + + //-------------------------------------------------------------------------- + + /// \brief Compares two character sequences + /// + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(basic_string_view v) const noexcept; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param v view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(size_type pos, size_type count, basic_string_view v) const; + + /// \brief Compares two character sequences + /// + /// \param pos1 position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param v view to compare + /// \param pos2 position of the second character in this view to compare + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(size_type pos1, + size_type count1, + basic_string_view v, + size_type pos2, + size_type count2) const; + + /// \brief Compares two character sequences + /// + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(size_type pos, + size_type count, + const char_type* s) const; + + /// \brief Compares two character sequences + /// + /// \param pos position of the first character in this view to compare + /// \param count1 number of characters of this view to compare + /// \param s pointer to the character string to compare to + /// \param count2 number of characters of the given view to compare + /// \return negative value if this view is less than the other character + /// sequence, zero if the both character sequences are equal, positive + /// value if this view is greater than the other character sequence. + BPSTD_CPP14_CONSTEXPR int compare(size_type pos, + size_type count1, + const char_type* s, + size_type count2) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type find(basic_string_view v, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find(char_type c, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find(const char_type* s, + size_type pos, + size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type find(const char_type* s, + size_type pos = 0) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type rfind(basic_string_view v, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type rfind(char_type c, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type rfind(const char_type* s, + size_type pos, + size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type rfind(const char_type* s, + size_type pos = npos) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type find_first_of(basic_string_view v, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_of(char_type c, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_of(const char_type* s, + size_type pos, + size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_of(const char_type* s, + size_type pos = 0) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type find_last_of(basic_string_view v, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_of(char_type c, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_of(const char_type* s, + size_type pos, size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_of(const char_type* s, + size_type pos = npos) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type find_first_not_of(basic_string_view v, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_not_of(char_type c, + size_type pos = 0) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_not_of(const char_type* s, + size_type pos, + size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type find_first_not_of(const char_type* s, + size_type pos = 0) const; + + //-------------------------------------------------------------------------- + + BPSTD_CPP14_CONSTEXPR size_type find_last_not_of(basic_string_view v, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_not_of(char_type c, + size_type pos = npos) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_not_of(const char_type* s, + size_type pos, + size_type count) const; + BPSTD_CPP14_CONSTEXPR size_type find_last_not_of(const char_type* s, + size_type pos = npos) const; + + //-------------------------------------------------------------------------- + // Iterators + //-------------------------------------------------------------------------- + public: + + /// \{ + /// \brief Retrieves the begin iterator for this basic_string_view + /// + /// \return the begin iterator + BPSTD_CPP14_CONSTEXPR const_iterator begin() const noexcept; + BPSTD_CPP14_CONSTEXPR const_iterator cbegin() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the end iterator for this basic_string_view + /// + /// \return the end iterator + BPSTD_CPP14_CONSTEXPR const_iterator end() const noexcept; + BPSTD_CPP14_CONSTEXPR const_iterator cend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse begin iterator for this basic_string_view + /// + /// \return the reverse begin iterator + BPSTD_CPP14_CONSTEXPR const_reverse_iterator rbegin() const noexcept; + BPSTD_CPP14_CONSTEXPR const_reverse_iterator rend() const noexcept; + /// \} + + /// \{ + /// \brief Retrieves the reverse end iterator for this basic_string_view + /// + /// \return the reverse end iterator + BPSTD_CPP14_CONSTEXPR const_reverse_iterator crbegin() const noexcept; + BPSTD_CPP14_CONSTEXPR const_reverse_iterator crend() const noexcept; + /// \} + + //-------------------------------------------------------------------------- + // Private Member + //-------------------------------------------------------------------------- + private: + + const char_type* m_str; ///< The internal string type + size_type m_size; ///< The size of this string + + /// \brief Checks whether \p c is one of the characters in \p str + /// + /// \param c the character to check + /// \param str the characters to compare against + /// \return true if \p c is one of the characters in \p str + static BPSTD_CPP14_CONSTEXPR bool is_one_of(CharT c, basic_string_view str); + }; + + template + constexpr typename bpstd::basic_string_view::size_type + basic_string_view::npos; + + //---------------------------------------------------------------------------- + // Public Functions + //---------------------------------------------------------------------------- + + /// \brief Overload for ostream output of basic_string_view + /// + /// \param o The output stream to print to + /// \param str the string to print + /// \return reference to the output stream + template + std::basic_ostream& operator<<(std::basic_ostream& o, + const basic_string_view& str); + + template + void swap(basic_string_view& lhs, + basic_string_view& rhs) noexcept; + + //---------------------------------------------------------------------------- + // Comparison Functions + //---------------------------------------------------------------------------- + + template + BPSTD_CPP14_CONSTEXPR bool + operator==(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR bool + operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR bool + operator<(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR bool + operator>(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR bool + operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR bool + operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) noexcept; + + //---------------------------------------------------------------------------- + // Type Aliases + //---------------------------------------------------------------------------- + + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + +} // namespace bpstd + +//============================================================================== +// definition : class : basic_string_view +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructor +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::basic_string_view::basic_string_view() + noexcept + : m_str{nullptr}, + m_size{0} +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::basic_string_view + ::basic_string_view(const std::basic_string& str) + noexcept + : m_str{str.c_str()}, + m_size{str.size()} +{ + +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::basic_string_view + ::basic_string_view(const char_type* str) + noexcept + : m_str{str}, + m_size{traits_type::length(str)} +{ + +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::basic_string_view + ::basic_string_view(const char_type* str, size_type count) + noexcept + : m_str{str}, + m_size{count} +{ + +} + +//------------------------------------------------------------------------------ +// Capacity +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::size() + const noexcept +{ + return m_size; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::length() + const noexcept +{ + return size(); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::max_size() + const noexcept +{ + return npos - 1; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::basic_string_view::empty() + const noexcept +{ + return m_size == 0u; +} + +//------------------------------------------------------------------------------ +// Element Access +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const typename bpstd::basic_string_view::char_type* + bpstd::basic_string_view::data() + const noexcept +{ + return m_str; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::const_reference + bpstd::basic_string_view::operator[](size_type pos) + const noexcept +{ + return m_str[pos]; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::const_reference + bpstd::basic_string_view::at(size_type pos) + const +{ + return (pos < m_size) + ? m_str[pos] + : (throw std::out_of_range{"Input out of range in basic_string_view::at"}), m_str[pos]; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::const_reference + bpstd::basic_string_view::front() + const noexcept +{ + return *m_str; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::basic_string_view::const_reference + bpstd::basic_string_view::back() + const noexcept +{ + return m_str[m_size-1]; +} + +//------------------------------------------------------------------------------ +// Modifiers +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +void bpstd::basic_string_view::remove_prefix(size_type n) + noexcept +{ + m_str += n, m_size -= n; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +void bpstd::basic_string_view::remove_suffix(size_type n) + noexcept +{ + m_size -= n; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +void bpstd::basic_string_view::swap(basic_string_view& v) + noexcept +{ + using std::swap; + swap(m_size,v.m_size); + swap(m_str,v.m_str); +} + +//------------------------------------------------------------------------------ +// Conversions +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::basic_string_view::operator + std::basic_string() + const +{ + return std::basic_string(m_str, m_size); +} + +//------------------------------------------------------------------------------ +// String Operations +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::copy(char_type* dest, + size_type count, + size_type pos) + const +{ + if(pos >= m_size) { + throw std::out_of_range("Index out of range in basic_string_view::copy"); + } + + const auto rcount = std::min(m_size - pos,count+1); + auto* const begin = m_str + pos; + auto* const end = m_str + pos + rcount; + for (auto it = begin; it != end; ++it) { + *dest = *it; + ++dest; + } + return rcount; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::basic_string_view + bpstd::basic_string_view::substr(size_type pos, + size_type len) + const +{ + const size_type max_length = pos > m_size ? 0 : m_size - pos; + + if (pos > size()) { + throw std::out_of_range("Index out of range in basic_string_view::substr"); + } + + return basic_string_view(m_str + pos, std::min(len, max_length) ); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(basic_string_view v) + const noexcept +{ + const size_type rlen = std::min(m_size,v.m_size); + const int compare = Traits::compare(m_str,v.m_str,rlen); + + if (compare != 0) { + return compare; + } + if (m_size < v.m_size) { + return -1; + } + if (m_size > v.m_size) { + return 1; + } + return 0; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(size_type pos, + size_type count, + basic_string_view v) + const +{ + return substr(pos,count).compare(v); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(size_type pos1, + size_type count1, + basic_string_view v, + size_type pos2, + size_type count2) + const +{ + return substr(pos1,count1).compare(v.substr(pos2,count2)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(const char_type* s) + const +{ + return compare(basic_string_view(s)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(size_type pos, + size_type count, + const char_type* s) + const +{ + return substr(pos, count).compare(basic_string_view(s)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +int + bpstd::basic_string_view::compare(size_type pos, + size_type count1, + const char_type* s, + size_type count2) + const +{ + return substr(pos, count1).compare(basic_string_view(s, count2)); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find(basic_string_view v, + size_type pos) + const +{ + // Can't find a substring if the substring is bigger than this + if (pos > size()) { + return npos; + } + if ((pos + v.size()) > size()) { + return npos; + } + + const auto offset = pos; + const auto increments = size() - v.size(); + + for (auto i = 0u; i <= increments; ++i) { + const auto j = i + offset; + if (substr(j, v.size()) == v) { + return j; + } + } + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find(char_type c, + size_type pos) + const +{ + return find(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find(const char_type* s, size_type pos, + size_type count) + const +{ + return find(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find(const char_type* s, + size_type pos) + const +{ + return find(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::rfind(basic_string_view v, + size_type pos) + const +{ + if (empty()) { + return v.empty() ? 0u : npos; + } + if (v.empty()) { + return std::min(size() - 1, pos); + } + if (v.size() > size()) { + return npos; + } + + auto i = std::min(pos, (size() - v.size())); + while (i != npos) { + if (substr(i, v.size()) == v) { + return i; + } + --i; + } + + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::rfind(char_type c, + size_type pos) + const +{ + return rfind(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::rfind(const char_type* s, + size_type pos, + size_type count) + const +{ + return rfind(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::rfind(const char_type* s, + size_type pos) + const +{ + return rfind(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_of(basic_string_view v, + size_type pos) + const +{ + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_of(char_type c, + size_type pos) + const +{ + return find_first_of(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_of(const char_type* s, + size_type pos, + size_type count) + const +{ + return find_first_of(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_of(const char_type* s, + size_type pos) + const +{ + return find_first_of(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_of(basic_string_view v, + size_type pos) + const +{ + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_of(char_type c, + size_type pos) + const +{ + return find_last_of(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_of(const char_type* s, + size_type pos, + size_type count) + const +{ + return find_last_of(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_of(const char_type* s, + size_type pos) + const +{ + return find_last_of(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_not_of(basic_string_view v, + size_type pos) + const +{ + const auto max_index = size(); + for (auto i = pos; i < max_index; ++i) { + if (!is_one_of(m_str[i],v)) { + return i; + } + } + + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_not_of(char_type c, + size_type pos) + const +{ + return find_first_not_of(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_not_of(const char_type* s, + size_type pos, + size_type count) + const +{ + return find_first_not_of(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_first_not_of(const char_type* s, + size_type pos) + const +{ + return find_first_not_of(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_not_of(basic_string_view v, + size_type pos) + const +{ + if (empty()) { + return npos; + } + const auto max_index = std::min(size() - 1, pos); + for (auto i = 0u; i <= max_index; ++i) { + const auto j = max_index - i; + + if (!is_one_of(m_str[j],v)) { + return j; + } + } + + return npos; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_not_of(char_type c, + size_type pos) + const +{ + return find_last_not_of(basic_string_view(&c, 1), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_not_of(const char_type* s, + size_type pos, + size_type count) + const +{ + return find_last_not_of(basic_string_view(s, count), pos); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::size_type + bpstd::basic_string_view::find_last_not_of(const char_type* s, + size_type pos) + const +{ + return find_last_not_of(basic_string_view(s), pos); +} + +//------------------------------------------------------------------------------ +// Iterator +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_iterator + bpstd::basic_string_view::begin() + const noexcept +{ + return m_str; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_iterator + bpstd::basic_string_view::cbegin() + const noexcept +{ + return begin(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_iterator + bpstd::basic_string_view::end() + const noexcept +{ + return m_str + m_size; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_iterator + bpstd::basic_string_view::cend() + const noexcept +{ + return cend(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_reverse_iterator + bpstd::basic_string_view::rbegin() + const noexcept +{ + return const_reverse_iterator{end()}; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_reverse_iterator + bpstd::basic_string_view::crbegin() + const noexcept +{ + return rbegin(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_reverse_iterator + bpstd::basic_string_view::rend() + const noexcept +{ + return const_reverse_iterator{begin()}; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +typename bpstd::basic_string_view::const_reverse_iterator + bpstd::basic_string_view::crend() + const noexcept +{ + return crend(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::basic_string_view::is_one_of(CharT c, + basic_string_view str) +{ + for (auto s : str) { + if (Traits::eq(c,s)) { + return true; + } + } + return false; +} + +//------------------------------------------------------------------------------ +// Public Functions +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +std::basic_ostream& + bpstd::operator<<(std::basic_ostream& o, + const basic_string_view& str) +{ + o.write(str.data(),static_cast(str.size())); + return o; +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::swap(basic_string_view& lhs, + basic_string_view& rhs) + noexcept +{ + lhs.swap(rhs); +} + +//------------------------------------------------------------------------------ +// Comparison Functions +//------------------------------------------------------------------------------ + +namespace bpstd { + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator==(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) == 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator==(basic_string_view lhs, const CharT* rhs) + noexcept + { + return lhs == basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator==(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) == rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator==(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) == rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator==(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs == basic_string_view(rhs); + } + + //---------------------------------------------------------------------------- + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator!=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) != 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator!=(const basic_string_view& lhs, const CharT* rhs) + noexcept + { + return lhs != basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator!=(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) != rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator!=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) != rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator!=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs != basic_string_view(rhs); + } + //---------------------------------------------------------------------------- + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) < 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<(const basic_string_view& lhs, const CharT* rhs) + noexcept + { + return lhs < basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) < rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator<(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) < rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator<(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs < basic_string_view(rhs); + } + + //---------------------------------------------------------------------------- + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) > 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>(const basic_string_view& lhs, const CharT* rhs) + noexcept + { + return lhs > basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) > rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator>(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) > rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator>(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs > basic_string_view(rhs); + } + + //---------------------------------------------------------------------------- + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) <= 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<=(const basic_string_view& lhs, const CharT* rhs) + noexcept + { + return lhs <= basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator<=(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) <= rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator<=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) <= rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator<=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs <= basic_string_view(rhs); + } + + //---------------------------------------------------------------------------- + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>=(const basic_string_view& lhs, + const basic_string_view& rhs) + noexcept + { + return lhs.compare(rhs) >= 0; + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>=(const basic_string_view& lhs, const CharT* rhs) + noexcept + { + return lhs >= basic_string_view(rhs); + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + bool operator>=(const CharT* lhs, const basic_string_view& rhs) + noexcept + { + return basic_string_view(lhs) >= rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator>=(const std::basic_string& lhs, + const basic_string_view& rhs) + { + return basic_string_view(lhs) >= rhs; + } + + template + inline BPSTD_INLINE_VISIBILITY + bool operator>=(const basic_string_view& lhs, + const std::basic_string& rhs) + { + return lhs >= basic_string_view(rhs); + } + +} // namespace bpstd + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_STRING_VIEW_HPP */ diff --git a/src/libs/vmisc/bpstd/tuple.hpp b/src/libs/vmisc/bpstd/tuple.hpp new file mode 100644 index 000000000..0c7e3753d --- /dev/null +++ b/src/libs/vmisc/bpstd/tuple.hpp @@ -0,0 +1,293 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file tuple.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_TUPLE_HPP +#define BPSTD_TUPLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "type_traits.hpp" // invoke_result +#include "utility.hpp" // index_sequence, forward +#include "functional.hpp" // invoke + +#include // std::tuple_element, and to proxy API +#include // std::size_t + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // class : tuple + //============================================================================ + + template + using tuple = std::tuple; + + //============================================================================ + // utilities : tuple + //============================================================================ + + template + using tuple_element = std::tuple_element; + + template + using tuple_element_t = typename tuple_element::type; + + //---------------------------------------------------------------------------- + + template + using tuple_size = std::tuple_size; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto tuple_size_v = tuple_size::value; +#endif + + //============================================================================ + // non-member functions : class : tuple + //============================================================================ + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + namespace detail { + template + struct is_tuple : false_type{}; + + template + struct is_tuple> : true_type{}; + } // namespace detail + + template >::value && is_lvalue_reference::value>> + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + tuple_element_t>& + get(Tuple&& t) noexcept + { + return std::get(t); + } + + template >::value && !is_lvalue_reference::value>> + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + tuple_element_t>&& + get(Tuple&& t) noexcept + { + return bpstd::move(std::get(t)); + } + + template + BPSTD_CPP14_CONSTEXPR T& get(tuple& t) noexcept; + template + BPSTD_CPP14_CONSTEXPR T&& get(tuple&& t) noexcept; + template + BPSTD_CPP14_CONSTEXPR const T& get(const tuple& t) noexcept; + template + BPSTD_CPP14_CONSTEXPR const T&& get(const tuple&& t) noexcept; + + //---------------------------------------------------------------------------- + + namespace detail { + + // primary template left undefined + template + struct apply_result_impl; + + template + struct apply_result_impl, Tuple> + : invoke_result...>{}; + + template + struct apply_result : apply_result_impl< + Fn, + make_index_sequence>::value>, + Tuple + >{}; + + template + using apply_result_t = typename apply_result::type; + } // namespace detail + + /// \brief Invokes the function \p fn using the arguments in \p tuple + /// + /// This invokes \p fn as if it were a call to bpstd::invoke using the + /// arguments in \p tuple + /// + /// \param fn the function to invoke + /// \param tuple the tuple of arguments to pass to fn + /// \return the result from \p fn + template + constexpr detail::apply_result_t apply(Fn&& fn, Tuple&& tuple); + + /// \brief Constructs a type \p T using the arguments in \p tuple + /// + /// \tparam T the type to construct + /// \param tuple the tuple of arguments to pass to T's constructor + template + constexpr T make_from_tuple(Tuple&& tuple); + +} // namespace bpstd + +//============================================================================== +// definitions : non-member functions : class : tuple +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +namespace bpstd { namespace detail { + + template + struct index_of_impl; + + template + struct index_of_impl + : index_of_impl{}; + + template + struct index_of_impl + : integral_constant{}; + + template + struct index_of : index_of_impl{}; + +}} // namespace bpstd::detail + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T& bpstd::get(tuple& t) + noexcept +{ + return std::get::value>(t); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T&& bpstd::get(tuple&& t) + noexcept +{ + return move(std::get::value>(t)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const T& bpstd::get(const tuple& t) + noexcept +{ + return std::get::value>(t); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const T&& bpstd::get(const tuple&& t) + noexcept +{ + return move(std::get::value>(t)); +} + +//============================================================================== +// definition : apply +//============================================================================== + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below +#endif + +namespace bpstd { + namespace detail { + template + inline BPSTD_INLINE_VISIBILITY constexpr + apply_result_t apply_impl(Fn&& fn, Tuple&& tuple, index_sequence) + { + return ::bpstd::invoke( + bpstd::forward(fn), + std::get(bpstd::forward(tuple))... + ); + } + } // namespace detail +} // namespace bpstd + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::detail::apply_result_t bpstd::apply(Fn&& fn, Tuple&& tuple) +{ + return detail::apply_impl( + bpstd::forward(fn), + bpstd::forward(tuple), + make_index_sequence>::value>{} + ); +} + +//============================================================================== +// definition : make_from_tuple +//============================================================================== + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4100) // MSVC warns that 'tuple' is not used below +#endif + +namespace bpstd { + namespace detail { + template + inline BPSTD_INLINE_VISIBILITY constexpr + T make_from_tuple_impl(Tuple&& tuple, index_sequence) + { + return T(std::get(bpstd::forward(tuple))...); + } + } // namespace detail +} // namespace bpstd + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T bpstd::make_from_tuple(Tuple&& tuple) +{ + return detail::make_from_tuple_impl( + bpstd::forward(tuple), + make_index_sequence>::value>{} + ); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_TUPLE_HPP */ diff --git a/src/libs/vmisc/bpstd/type_traits.hpp b/src/libs/vmisc/bpstd/type_traits.hpp new file mode 100644 index 000000000..d1f599e8e --- /dev/null +++ b/src/libs/vmisc/bpstd/type_traits.hpp @@ -0,0 +1,1398 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file type_traits.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_TYPE_TRAITS_HPP +#define BPSTD_TYPE_TRAITS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "detail/move.hpp" // move, forward +#include "detail/invoke.hpp" // detail::INVOKE + +#include +#include // std::size_t + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +// GCC versions prior to gcc-5 did not implement the type traits for triviality +// in completion. Several traits are implemented under a different names from +// pre-standardization, such as 'has_trivial_copy_destructor' instead of +// 'is_trivially_destructible'. However, most of these cannot be implemented +// without compiler support. +// +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2014 +#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5 +# define BPSTD_HAS_TRIVIAL_TYPE_TRAITS 0 +#else +# define BPSTD_HAS_TRIVIAL_TYPE_TRAITS 1 +#endif + +namespace bpstd { + + //============================================================================ + // Type constants + //============================================================================ + + template + using integral_constant = std::integral_constant; + + template + using bool_constant = integral_constant; + + using std::true_type; + using std::false_type; + + template + struct type_identity { + using type = T; + }; + + namespace detail { + template + struct make_void : type_identity{}; + } // namespace detail + + template + using void_t = typename detail::make_void::type; + + //============================================================================ + // Metafunctions + //============================================================================ + + template + using enable_if = std::enable_if; + + template + using enable_if_t = typename enable_if::type; + + //---------------------------------------------------------------------------- + + template + using conditional = std::conditional; + + template + using conditional_t = typename conditional::type; + + /// \brief Type trait to determine the bool_constant from a logical + /// AND operation of other bool_constants + /// + /// The result is aliased as \c ::value + template + struct conjunction; + + template + struct conjunction : B1{}; + + template + struct conjunction + : conditional_t, B1>{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto disconjunction_v = conjunction::value; +#endif + + //---------------------------------------------------------------------------- + + /// \brief Type trait to determine the \c bool_constant from a logical + /// OR operations of other bool_constant + /// + /// The result is aliased as \c ::value + template + struct disjunction : false_type { }; + + template + struct disjunction : B1{}; + + template + struct disjunction + : conditional_t>{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto disjunction_v = disjunction::value; +#endif + + //---------------------------------------------------------------------------- + + /// \brief Utility metafunction for negating a bool_constant + /// + /// The result is aliased as \c ::value + /// + /// \tparam B the constant + template + struct negation : bool_constant(B::value)>{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto negation_v = negation::value; +#endif + + //---------------------------------------------------------------------------- + + template + using invoke_result = detail::invoke_result; + + template + using invoke_result_t = typename invoke_result::type; + + //---------------------------------------------------------------------------- + + namespace detail { + + template + struct is_invocable_return : std::is_convertible, R>{}; + + template + struct is_invocable_return : false_type{}; + + } // namespace detail + + template + using is_invocable = detail::is_invocable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_invocable_v = is_invocable::value; +#endif + + //---------------------------------------------------------------------------- + + template + struct is_invocable_r + : detail::is_invocable_return::value, R, Fn, Args...>{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_invocable_r_v = is_invocable_r::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_invocable = detail::is_nothrow_invocable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_invocable_v = is_nothrow_invocable::value; +#endif + + //---------------------------------------------------------------------------- + + template + struct is_nothrow_invocable_r + : detail::is_invocable_return::value, R, Fn, Args...>{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_invocable_r_v + = is_nothrow_invocable_r::value; +#endif + + //============================================================================ + // Type categories + //============================================================================ + + template + using is_void = std::is_void; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_void_v = is_void::value; +#endif + + //---------------------------------------------------------------------------- + + template + struct is_null_pointer : false_type{}; + + template <> + struct is_null_pointer : true_type{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_null_pointer_v = is_null_pointer::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_array = std::is_array; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_array_v = is_array::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_pointer = std::is_pointer; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_pointer_v = is_pointer::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_enum = std::is_enum; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_enum_v = is_enum::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_union = std::is_union; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_union_v = is_union::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_class = std::is_class; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_class_v = is_class::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_function = std::is_function; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_function_v = is_function::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_object = std::is_object; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_object_v = is_object::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_scalar = std::is_scalar; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_scalar_v = is_scalar::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_compound = std::is_compound; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_compound_v = is_compound::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_integral = std::is_integral; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_integral_v = is_integral::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_floating_point = std::is_floating_point; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_floating_point_v = is_floating_point::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_fundamental = std::is_fundamental; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_fundamental_v = is_fundamental::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_arithmetic = std::is_arithmetic; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_arithmetic_v = is_arithmetic::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_reference = std::is_reference; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_reference_v = is_reference::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_lvalue_reference = std::is_lvalue_reference; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_lvalue_reference_v = is_lvalue_reference::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_rvalue_reference = std::is_rvalue_reference; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_rvalue_reference_v = is_rvalue_reference::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_member_pointer = std::is_member_pointer; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_member_pointer_v = is_member_pointer::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_member_object_pointer = std::is_member_object_pointer; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_member_object_pointer_v = is_member_object_pointer::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_member_function_pointer = std::is_member_function_pointer; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_member_function_pointer_v = is_member_function_pointer::value; +#endif + + //============================================================================ + // Type properties + //============================================================================ + + template + using is_const = std::is_const; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_const_v = is_const::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_volatile = std::is_volatile; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_volatile_v = is_volatile::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_empty = std::is_empty; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_empty_v = is_empty::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_polymorphic = std::is_polymorphic; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_polymorphic_v = is_polymorphic::value; +#endif + + //---------------------------------------------------------------------------- + +#if __cplusplus >= 201402L + // is_final is only defined in C++14 + template + struct is_final : std::is_final{}; +#else + // is_final requires compiler-support to implement. + // Without this support, the best we can do is require explicit + // specializations of 'is_final' for any types that are known to be final + template + struct is_final : false_type{}; +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_final_v = is_final::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_abstract = std::is_abstract; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_abstract_v = is_abstract::value; +#endif + + //---------------------------------------------------------------------------- + + // is_aggregate is only defined in C++17 +#if __cplusplus >= 201703L + + template + using is_aggregate = std::is_aggregate; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_aggregate_v = is_aggregate::value; +#endif +#endif + + //---------------------------------------------------------------------------- + + template + using is_trivial = std::is_trivial; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivial_v = is_trivial::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_copyable = std::is_trivially_copyable; + +#else + + // std::is_trivially_copyable is not implemented in gcc < 5, and unfortunately + // can't be implemented without compiler intrinsics. This definition is + // left out to avoid problems + template + using is_trivially_copyable = false_type; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_copyable_v = is_trivially_copyable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_standard_layout = std::is_standard_layout; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_standard_layout_v = is_standard_layout::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_literal_type = std::is_literal_type; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_literal_type_v = is_literal_type::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_pod = std::is_pod; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_pod_v = is_pod::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_signed = std::is_signed; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_signed_v = is_signed::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_unsigned = std::is_unsigned; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_unsigned_v = is_unsigned::value; +#endif + + //---------------------------------------------------------------------------- + + template + struct is_bounded_array : false_type{}; + + template + struct is_bounded_array : true_type{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_bounded_array_v = is_bounded_array::value; +#endif + + //---------------------------------------------------------------------------- + + + template + struct is_unbounded_array : false_type{}; + + template + struct is_unbounded_array : true_type{}; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_unbounded_array_v = is_unbounded_array::value; +#endif + + //---------------------------------------------------------------------------- + + // has_unique_object_representation only defined in C++17 +#if __cplusplus >= 201703L + template + using has_unique_object_representations = std::has_unique_object_representations; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto has_unique_object_representations_v = has_unique_object_representations::value; +#endif +#endif + + //============================================================================ + // Type Modification + //============================================================================ + + template + using remove_cv = std::remove_cv; + + template + using remove_cv_t = typename remove_cv::type; + + //---------------------------------------------------------------------------- + + template + using remove_const = std::remove_const; + + template + using remove_const_t = typename remove_const::type; + + //---------------------------------------------------------------------------- + + template + using remove_volatile = std::remove_volatile; + + template + using remove_volatile_t = typename remove_volatile::type; + + //---------------------------------------------------------------------------- + + template + using add_cv = std::add_cv; + + template + using add_cv_t = typename add_cv::type; + + //---------------------------------------------------------------------------- + + template + using add_const = std::add_const; + + template + using add_const_t = typename add_const::type; + + //---------------------------------------------------------------------------- + + template + using add_volatile = std::add_volatile; + + template + using add_volatile_t = typename add_volatile::type; + + //---------------------------------------------------------------------------- + + template + using make_signed = std::make_signed; + + template + using make_signed_t = typename make_signed::type; + + //---------------------------------------------------------------------------- + + template + using make_unsigned = std::make_unsigned; + + template + using make_unsigned_t = typename make_unsigned::type; + + //---------------------------------------------------------------------------- + + template + using remove_reference = std::remove_reference; + + template + using remove_reference_t = typename remove_reference::type; + + //---------------------------------------------------------------------------- + + template + using add_lvalue_reference = std::add_lvalue_reference; + + template + using add_lvalue_reference_t = typename add_lvalue_reference::type; + + //---------------------------------------------------------------------------- + + template + using add_rvalue_reference = std::add_rvalue_reference; + + template + using add_rvalue_reference_t = typename add_rvalue_reference::type; + + //---------------------------------------------------------------------------- + + template + using remove_pointer = std::remove_pointer; + + template + using remove_pointer_t = typename remove_pointer::type; + + //---------------------------------------------------------------------------- + + template + using add_pointer = std::add_pointer; + + template + using add_pointer_t = typename add_pointer::type; + + //---------------------------------------------------------------------------- + + template + using remove_extent = std::remove_extent; + + template + using remove_extent_t = typename remove_extent::type; + + //---------------------------------------------------------------------------- + + template + using remove_all_extents = std::remove_all_extents; + + template + using remove_all_extents_t = typename remove_all_extents::type; + + //---------------------------------------------------------------------------- + + template + using remove_cvref = remove_cv>; + + template + using remove_cvref_t = typename remove_cvref::type; + + //============================================================================ + // Type Transformation + //============================================================================ + + template + struct aligned_storage + { + struct type { + alignas(Align) char storage[Size]; + }; + }; + + template + using aligned_storage_t = typename aligned_storage::type; + + //---------------------------------------------------------------------------- + + namespace detail { + + template + struct largest; + + template + struct largest + : largest<(Size0 > Size1 ? Size0 : Size1), Sizes...>{}; + + template + struct largest : integral_constant{}; + + } // namespace detail + + // gcc < 5 does not implement 'std::aligned_union', despite it being a type + // in the C++11 standard -- so it's implemented here to ensure that its + // available. + template + struct aligned_union + { + static constexpr std::size_t alignment_value = detail::largest::value; + + struct type + { + alignas(alignment_value) char buffer[detail::largest::value]; + }; + }; + + template + constexpr std::size_t aligned_union::alignment_value; + + template + using aligned_union_t = typename aligned_union::type; + + //---------------------------------------------------------------------------- + + template + using decay = std::decay; + + template + using decay_t = typename decay::type; + + //---------------------------------------------------------------------------- + + template + using common_type = std::common_type; + + template + using common_type_t = typename common_type::type; + + //---------------------------------------------------------------------------- + + namespace detail { + + template + struct underlying_type_impl : type_identity{}; + + template + struct underlying_type_impl{}; + + } // namespace detail + + template + struct underlying_type : detail::underlying_type_impl::value, T>{}; + + template + using underlying_type_t = typename underlying_type::type; + + //---------------------------------------------------------------------------- + + template + using result_of = std::result_of; + + template + using result_of_t = typename result_of::type; + + //============================================================================ + // Supported Operations + //============================================================================ + + template + using is_constructible = std::is_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_constructible_v = is_constructible::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_constructible = std::is_trivially_constructible; + +#else + + // std::is_trivially_constructible is not implemented in gcc < 5, and + // there exists no utilities to implement it in the language without extensions. + // This is left defined to false_type so that the trait may be used, despite + // yielding incorrect results + template + using is_trivially_constructible = false_type; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_constructible_v = is_trivially_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_constructible = std::is_nothrow_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_constructible_v = is_nothrow_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_default_constructible = std::is_default_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_default_constructible_v = is_default_constructible::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_default_constructible = std::is_trivially_default_constructible; + +#else + + // std::is_trivially_default_constructible is not implemented in gcc < 5, + // however there exists a non-standard + // 'std::has_trivial_default_constructor' which performs a similar check + template + using is_trivially_default_constructible = std::has_trivial_default_constructor; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_default_constructible_v = is_trivially_default_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_default_constructible = std::is_nothrow_default_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_default_constructible_v = is_nothrow_default_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_copy_constructible = std::is_copy_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_copy_constructible_v = is_copy_constructible::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_copy_constructible = std::is_trivially_copy_constructible; + +#else + + // std::is_trivially_copy_constructible is not implemented in gcc < 5, + // however there exists a non-standard + // 'std::has_trivial_copy_constructor' which performs a similar check + template + using is_trivially_copy_constructible = std::has_trivial_copy_constructor; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_copy_constructible_v = is_trivially_copy_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_copy_constructible = std::is_nothrow_copy_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_copy_constructible_v = is_nothrow_copy_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_move_constructible = std::is_move_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_move_constructible_v = is_move_constructible::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_move_constructible = std::is_trivially_move_constructible; + +#else + + // std::is_trivially_move_constructible is not implemented in gcc < 5, and + // there exists no utilities to implement it in the language without extensions. + // This is left defined to false_type so that the trait may be used, despite + // yielding incorrect results + template + using is_trivially_move_constructible = false_type; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_move_constructible_v = is_trivially_move_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_move_constructible = std::is_nothrow_move_constructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_move_constructible_v = is_nothrow_move_constructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_assignable = std::is_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_assignable_v = is_assignable::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_assignable = std::is_trivially_assignable; + +#else + + // std::is_trivially_assignable is not implemented in gcc < 5, and + // there exists no utilities to implement it in the language without extensions. + // This is left defined to false_type so that the trait may be used, despite + // yielding incorrect results + template + using is_trivially_assignable = false_type; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_assignable_v = is_trivially_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_assignable = std::is_nothrow_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_assignable_v = is_nothrow_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_copy_assignable = std::is_copy_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_copy_assignable_v = is_copy_assignable::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_copy_assignable = std::is_trivially_copy_assignable; + +#else + + // std::is_trivially_copy_assignable is not implemented in gcc < 5, + // however there exists a non-standard + // 'std::has_trivial_copy_assign' which performs a similar check + template + using is_trivially_copy_assignable = std::has_trivial_copy_assign; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_copy_assignable_v = is_trivially_copy_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_copy_assignable = std::is_nothrow_copy_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_copy_assignable_v = is_nothrow_copy_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_move_assignable = std::is_move_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_move_assignable_v = is_move_assignable::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_move_assignable = std::is_trivially_move_assignable; + +#else + + // std::is_trivially_move_assignable is not implemented in gcc < 5, and + // there exists no utilities to implement it in the language without extensions. + // This is left defined to false_type so that the trait may be used, despite + // yielding incorrect results + template + using is_trivially_move_assignable = false_type; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_move_assignable_v = is_trivially_move_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_move_assignable = std::is_nothrow_move_assignable; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_move_assignable_v = is_nothrow_move_assignable::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_destructible = std::is_destructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_destructible_v = is_destructible::value; +#endif + + //---------------------------------------------------------------------------- + +#if BPSTD_HAS_TRIVIAL_TYPE_TRAITS + + template + using is_trivially_destructible = std::is_trivially_destructible; + +#else + + // std::is_trivially_destructible is not implemented in gcc < 5, however there + // exists a non-standard '__has_trivial_destructor' which performs a + // similar check + template + using is_trivially_destructible = bool_constant<(__has_trivial_destructor(T))>; + +#endif + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_trivially_destructible_v = is_trivially_destructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_nothrow_destructible = std::is_nothrow_destructible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_destructible_v = is_nothrow_destructible::value; +#endif + + //---------------------------------------------------------------------------- + + template + using has_virtual_destructor = std::has_virtual_destructor; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto has_virtual_destructor_v = has_virtual_destructor::value; +#endif + + //============================================================================ + // Relationship + //============================================================================ + + template + using is_same = std::is_same; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_same_v = is_same::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_base_of = std::is_base_of; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_base_of_v = is_base_of::value; +#endif + + //---------------------------------------------------------------------------- + + template + using is_convertible = std::is_convertible; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_convertible_v = is_convertible::value; +#endif + + //---------------------------------------------------------------------------- + + namespace detail { + + template + struct is_nothrow_convertible_impl : false_type{}; + + template + struct is_nothrow_convertible_impl + { + static void test(To) noexcept; + + BPSTD_CPP17_INLINE static constexpr auto value = + noexcept(test(std::declval())); + }; + + } // namespace detail + + template + using is_nothrow_convertible = bool_constant< + detail::is_nothrow_convertible_impl::value,From,To>::value + >; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_convertible_v = is_nothrow_convertible::value; +#endif + + namespace detail { + namespace adl_swap { + + void swap(); + + //------------------------------------------------------------------------ + + template + struct is_std_swappable_with : false_type{}; + + template + struct is_std_swappable_with + : conjunction< + is_move_constructible>>, + is_move_assignable>>, + is_lvalue_reference + >{}; + + template + struct is_nothrow_std_swappable_with : false_type{}; + + template + struct is_nothrow_std_swappable_with + : conjunction< + is_nothrow_move_constructible>>, + is_nothrow_move_assignable>>, + is_lvalue_reference + >{}; + + //------------------------------------------------------------------------ +#if !defined(_MSC_FULL_VER) || _MSC_FULL_VER >= 191426428 + + template + using detect_adl_swap = decltype(swap(std::declval(), std::declval())); + + template class Op, typename = void> + struct is_adl_swappable_with : false_type{}; + + template class Op> + struct is_adl_swappable_with>> + : true_type{}; + + template ::value> + struct is_nothrow_adl_swappable_with : false_type{}; + + template + struct is_nothrow_adl_swappable_with + : bool_constant(), std::declval()))>{}; +#endif + + } // namespace adl_swap + +#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 191426428 + + // MSVC 2017 15.7 or above is required for expression SFINAE. + // I'm not sure if 'is_swappable_with' is properly implementable without + // it, since we need to test calling of 'swap' unqualified. + // For now, the best we can do is test whether std::swap works, until a + // more full-featured compiler is used. + + template + struct is_swappable_with + : adl_swap::is_std_swappable_with{}; + + template + struct is_nothrow_swappable_with + : adl_swap::is_nothrow_std_swappable_with{}; + +#else + + template + struct is_swappable_with + : conditional_t::value, + adl_swap::is_adl_swappable_with, + adl_swap::is_std_swappable_with + >{}; + + template + struct is_nothrow_swappable_with + : conditional_t::value, + adl_swap::is_nothrow_adl_swappable_with, + adl_swap::is_nothrow_std_swappable_with + >{}; + +#endif + + } // namespace detail + + template + using is_swappable_with = detail::is_swappable_with&,remove_cvref_t&>; + + template + using is_swappable = is_swappable_with; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_swappable_with_v = is_swappable_with::value; + + template + BPSTD_CPP17_INLINE constexpr auto is_swappable_v = is_swappable::value; +#endif + + template + using is_nothrow_swappable_with = detail::is_nothrow_swappable_with&,remove_cvref_t&>; + + template + using is_nothrow_swappable = is_nothrow_swappable_with; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_swappable_with_v = is_nothrow_swappable_with::value; + + template + BPSTD_CPP17_INLINE constexpr auto is_nothrow_swappable_v = is_nothrow_swappable_with::value; +#endif + +} // namespace bpstd + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_TYPE_TRAITS_HPP */ diff --git a/src/libs/vmisc/bpstd/utility.hpp b/src/libs/vmisc/bpstd/utility.hpp new file mode 100644 index 000000000..0bef0e52c --- /dev/null +++ b/src/libs/vmisc/bpstd/utility.hpp @@ -0,0 +1,382 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file utility.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_UTILITY_HPP +#define BPSTD_UTILITY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "detail/move.hpp" // IWYU pragma: export +#include "type_traits.hpp" // add_const_t + +#include // to proxy the API +#include // std::size_t + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // struct : in_place_t + //============================================================================ + + /// \brief This function is a special disambiguation tag for variadic + /// functions, used in any and optional + /// + /// \note Calling this function results in undefined behaviour. + struct in_place_t + { + explicit in_place_t() = default; + }; + BPSTD_CPP17_INLINE constexpr in_place_t in_place{}; + + //============================================================================ + // in_place_type_t + //============================================================================ + + /// \brief This function is a special disambiguation tag for variadic + /// functions, used in any and optional + /// + /// \note Calling this function results in undefined behaviour. + template + struct in_place_type_t + { + explicit in_place_type_t() = default; + }; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr in_place_type_t in_place_type{}; +#endif + + //============================================================================ + // in_place_index_t + //============================================================================ + + /// \brief This function is a special disambiguation tag for variadic + /// functions, used in any and optional + /// + /// \note Calling this function results in undefined behaviour. + template struct in_place_index_t + { + explicit in_place_index_t() = default; + }; + +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr in_place_index_t in_place_index{}; +#endif + + //============================================================================ + // non-member functions + //============================================================================ + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + /// \brief Moves a type \p x if it move-construction is non-throwing + /// + /// \param x the parameter to move + /// \return an rvalue reference if nothrow moveable, const reference otherwise + template + constexpr typename bpstd::conditional< + !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, + const T&, + T&& + >::type move_if_noexcept(T& x) noexcept; + + /// \brief Forms an lvalue reference to const type of t + /// + /// \param t the type to form an lvalue reference to + /// \return the reference to const T + template + constexpr add_const_t& as_const(T& t) noexcept; + template + void as_const(const T&&) = delete; + + /// \brief Replaces the value of obj with new_value and returns the old value + /// of obj. + /// + /// \pre \p T must meet the requirements of MoveConstructible. + /// + /// \pre It must be possible to move-assign objects of type \p U to objects of + /// type \p T + /// + /// \param obj object whose value to replace + /// \param new_value the value to assign to obj + template + BPSTD_CPP14_CONSTEXPR T exchange(T& obj, U&& new_value); + + //============================================================================ + // class : pair + //============================================================================ + + template + using pair = std::pair; + + //============================================================================ + // non-member functions : class : pair + //============================================================================ + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + // C++11 does not implement const pair&& + template + constexpr conditional_t& get(pair& p) noexcept; + template + constexpr conditional_t&& get(pair&& p) noexcept; + template + constexpr const conditional_t& get(const pair& p) noexcept; + template + constexpr const conditional_t&& get(const pair&& p) noexcept; + + template + constexpr T& get(pair& p) noexcept; + template + constexpr T&& get(pair&& p) noexcept; + template + constexpr const T& get(const pair& p) noexcept; + template + constexpr const T&& get(const pair&& p) noexcept; + + template + constexpr T& get(pair& p) noexcept; + template + constexpr const T& get(const pair& p) noexcept; + template + constexpr T&& get(pair&& p) noexcept; + template + constexpr const T&& get(const pair&& p) noexcept; + + //============================================================================ + // struct : integer_sequence + //============================================================================ + + template + struct integer_sequence + { + using value_type = T; + + static constexpr std::size_t size() noexcept { return sizeof...(Ints); } + }; + + template + using index_sequence = integer_sequence; + + namespace detail { + template + struct make_integer_sequence_impl + : make_integer_sequence_impl{}; + + template + struct make_integer_sequence_impl + : type_identity>{}; + + } // namespace detail + + template + using make_integer_sequence + = typename detail::make_integer_sequence_impl::type; + + template + using make_index_sequence = make_integer_sequence; + + template + using index_sequence_for = make_index_sequence; + +} // namespace bpstd + +//============================================================================== +// non-member functions +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +typename bpstd::conditional< + !bpstd::is_nothrow_move_constructible::value && bpstd::is_copy_constructible::value, + const T&, + T&& +>::type bpstd::move_if_noexcept(T& x) + noexcept +{ + using result_type = conditional_t< + !is_nothrow_move_constructible::value && is_copy_constructible::value, + const T&, + T&& + >; + + return static_cast(x); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::add_const_t& bpstd::as_const(T& t) + noexcept +{ + return t; +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T bpstd::exchange(T& obj, U&& new_value) +{ + auto old_value = bpstd::move(obj); + obj = bpstd::forward(new_value); + return old_value; +} + +//============================================================================== +// definitions : non-member functions : class : pair +//============================================================================== + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::conditional_t& + bpstd::get(pair& p) + noexcept +{ + static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); + + return std::get(p); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::conditional_t&& + bpstd::get(pair&& p) + noexcept +{ + static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); + + return move(std::get(p)); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const bpstd::conditional_t& + bpstd::get(const pair& p) + noexcept +{ + static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); + + return std::get(p); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const bpstd::conditional_t&& + bpstd::get(const pair&& p) + noexcept +{ + static_assert(N<=1, "N must be either 0 or 1 for get(pair)"); + + return move(std::get(p)); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T& bpstd::get(pair& p) + noexcept +{ + return p.first; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const T& bpstd::get(const pair& p) + noexcept +{ + return p.first; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T&& bpstd::get(pair&& p) + noexcept +{ + return move(p.first); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const T&& bpstd::get(const pair&& p) + noexcept +{ + return move(p.first); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T& bpstd::get(pair& p) + noexcept +{ + return p.second; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const T& bpstd::get(const pair& p) + noexcept +{ + return p.second; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +T&& bpstd::get(pair&& p) + noexcept +{ + return move(p.second); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +const T&& bpstd::get(const pair&& p) + noexcept +{ + return move(p.second); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_UTILITY_HPP */ diff --git a/src/libs/vmisc/bpstd/variant.hpp b/src/libs/vmisc/bpstd/variant.hpp new file mode 100644 index 000000000..2e8a5d3f7 --- /dev/null +++ b/src/libs/vmisc/bpstd/variant.hpp @@ -0,0 +1,1956 @@ +//////////////////////////////////////////////////////////////////////////////// +/// \file variant.hpp +/// +/// \brief This header provides definitions from the C++ header +//////////////////////////////////////////////////////////////////////////////// + +/* + The MIT License (MIT) + + Copyright (c) 2020 Matthew Rodusek All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef BPSTD_VARIANT_HPP +#define BPSTD_VARIANT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "detail/config.hpp" +#include "detail/enable_overload.hpp" // enable_overload_if +#include "detail/nth_type.hpp" +#include "detail/variant_base.hpp" +#include "detail/variant_visitors.hpp" +#include "detail/variant_traits.hpp" +#include "tuple.hpp" +#include "utility.hpp" // in_place_index_t, in_place_type_t +#include "type_traits.hpp" // conjunction +#include "functional.hpp" // less, greater, equal_to, etc + +#include // std::initializer_list +#include // std::uses_allocator +#include // std::exception +#include // std::size_t +#include // std::forward, std::move + +BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE + +namespace bpstd { + + //============================================================================ + // class : monostate + //============================================================================ + + struct monostate{}; + + constexpr bool operator==(monostate, monostate) noexcept; + constexpr bool operator!=(monostate, monostate) noexcept; + constexpr bool operator<(monostate, monostate) noexcept; + constexpr bool operator>(monostate, monostate) noexcept; + constexpr bool operator<=(monostate, monostate) noexcept; + constexpr bool operator>=(monostate, monostate) noexcept; + + //============================================================================ + // forward declaration : variant + //============================================================================ + + template + class variant; + + //========================================================================= + // trait : variant_size + //========================================================================= + + /// \{ + /// \brief Provides access to the number of alternatives in a possibly + /// cv-qualified variant as a compile-time constant expression. + /// + /// The result is accessible as ::value + template + struct variant_size; // not defined + + template + struct variant_size + : variant_size{}; + + template + struct variant_size + : variant_size{}; + + template + struct variant_size + : variant_size{}; + + template + struct variant_size> + : integral_constant{}; + /// \} + + /// \brief Helper variable template for extracting variant_size::value +#if BPSTD_HAS_TEMPLATE_VARIABLES + template + BPSTD_CPP17_INLINE constexpr auto variant_size_v = variant_size::value; +#endif + + //============================================================================ + // trait : variant_alternative + //============================================================================ + + /// \{ + /// \brief A metafunction for extracting the type at index \p I from the + /// (possibly CV-qualified) variant + /// + /// \note This template is not defined for non-variant types + /// + /// \note The result is only defined for I < sizeof...(Types) in variant + /// + /// \tparam I the index + /// \tparam T the type + template + struct variant_alternative; // not defined + + template + struct variant_alternative + : add_const::type>{}; + + template + struct variant_alternative + : add_volatile::type>{}; + + template + struct variant_alternative + : add_cv::type>{}; + + template + struct variant_alternative> + : detail::nth_type{}; + /// \} + + //---------------------------------------------------------------------------- + + /// \brief A helper template for extracting the ::type from + /// variant_alternative + /// + /// \tparam I the index + /// \tparam T the variant + template + using variant_alternative_t = typename variant_alternative::type; + + //============================================================================ + // globals : variant + //============================================================================ + + /// \brief This is a special value equal to the largest value + /// representable by the type std::size_t, used as the return type + /// of index() when valueless_by_exception() is true + BPSTD_CPP17_INLINE constexpr auto variant_npos = static_cast(-1); + + //============================================================================ + // class : bad_variant_access + //============================================================================ + + ////////////////////////////////////////////////////////////////////////// + /// \brief Exception thrown by variant + /// + /// bad_variant_access is the type of the exception thrown in the + /// following situations: + /// - get(std::variant) called with an index or type that does not match + /// the currently active alternative + /// - visit called to visit a variant that is valueless_by_exception + ////////////////////////////////////////////////////////////////////////// + class bad_variant_access : public std::exception + { + //-------------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------------- + public: + + /// \brief Constructs a new instance of bad_variant_access. + bad_variant_access() noexcept = default; + + //-------------------------------------------------------------------------- + // Observers + //-------------------------------------------------------------------------- + public: + + /// \brief returns an explanatory string of the exception + /// + /// \return string explaining the issue + const char* what() const noexcept override; + }; + + namespace detail { + + //========================================================================== + // trait : index_from + //========================================================================== + + template + struct index_from_impl; + + template + struct index_from_impl + : integral_constant{}; + + template + struct index_from_impl + : index_from_impl{}; + + template + struct index_from_impl + : integral_constant{}; + + /// \brief Type-trait to get the index of T in a list of Ts + template + struct index_from : index_from_impl<0,T,Ts...>{}; + + //========================================================================== + // trait : is_not_in_place + //========================================================================== + + /// \brief Type-trait for determining if 'T' is *not* an in_place type + template + struct is_not_in_place : true_type{}; + + template + struct is_not_in_place> : false_type{}; + + template + struct is_not_in_place> : false_type{}; + + template <> + struct is_not_in_place : false_type{}; + + //========================================================================== + // trait : index_of_constructible_alternative + //========================================================================== + + template + struct variant_f_impl; + + template + struct variant_f_impl + : variant_f_impl + { + using variant_f_impl::operator(); + + integral_constant operator()(T0); + }; + + // skip 'bool' overloads from consideration + template + struct variant_f_impl + : variant_f_impl + { + using variant_f_impl::operator(); + }; + + template + struct variant_f_impl + : variant_f_impl + { + using variant_f_impl::operator(); + }; + + template + struct variant_f_impl + : variant_f_impl + { + using variant_f_impl::operator(); + }; + + template + struct variant_f_impl + : variant_f_impl + { + using variant_f_impl::operator(); + }; + + template + struct variant_f_impl + { + // End recursion with a variant_npos + integral_constant operator()(...); + }; + + template + struct variant_f : variant_f_impl<0,Types...> {}; + + //-------------------------------------------------------------------------- + + /// \brief Type-trait to retrieve the index of the constructible alternative + /// as if presented by an overload set containing all T types. + /// + /// The index result is 'variant_npos' if no overload is valid + /// + /// If 'T' is a possibly CV-qualified bool, this will only yield an index + /// if 'Types...' contains a possible CV-qualified bool as well, to prevent + /// unintentional conversions from string literals and pointers. + template + struct index_of_constructible_alternative + : conditional_t< + is_same,bool>::value, + index_from...>, + decltype(std::declval>()(std::declval())) + >{}; + + template + struct constructible_alternative + : nth_type::value, Types...>{}; + + template + using constructible_alternative_t + = typename constructible_alternative::type; + + //========================================================================== + // trait : has_constructible_alternative + //========================================================================== + + /// \brief Type-trait to check whether an alternative may be constructed + /// when presented with all types as an overload set + template + struct has_constructible_alternative + : bool_constant<(index_of_constructible_alternative::value != variant_npos)>{}; + + template + struct can_construct_alternative_impl : false_type{}; + + template + struct can_construct_alternative_impl + : is_constructible,T>{}; + + template + using can_construct_alternative + = can_construct_alternative_impl::value,T,Types...>; + + template + struct can_assign_alternative_impl : false_type{}; + + template + struct can_assign_alternative_impl + : is_assignable,T>{}; + + template + using can_assign_alternative + = can_assign_alternative_impl::value,T,Types...>; + + } // namespace detail + + //============================================================================ + // class : variant + //============================================================================ + + ////////////////////////////////////////////////////////////////////////////// + /// \brief The class template variant represents a type-safe union. + /// + /// An instance of variant at any given time either holds a value of + /// one of its alternative types, or it holds no value (this state is hard + /// to achieve, \see valueless_by_exception ). + /// + /// As with unions, if a variant holds a value of some object type T, the + /// object representation of T is allocated directly within the object + /// representation of the variant itself. Variant is not allowed to allocate + /// additional (dynamic) memory. + /// + /// A variant is not permitted to hold references, arrays, or the type void. + /// Empty variants are also ill-formed (variant can be + /// used instead). + /// + /// A variant is permitted to hold the same type more than once, and to hold + /// differently cv-qualified versions of the same type. + /// + /// As with unions, the default-initialized variant holds a value of its + /// first alternative, unless that alternative is not default-constructible + /// (in which case default constructor won't compile: the helper class + /// monostate can be used to make such variants default-constructible) + /// + /// \tparam Types the types that may be stored in this variant. All types + /// must be (possibly cv-qualified) non-array object types + ////////////////////////////////////////////////////////////////////////////// + template + class variant + : detail::variant_base< + conjunction...>::value, + Types... + > + { + //-------------------------------------------------------------------------- + // Validation + //-------------------------------------------------------------------------- + + static_assert( + sizeof...(Types) > 0, + "A variant of 0 types is ill-formed. Use variant instead." + ); + static_assert( + conjunction>...>::value, + "A variant containing a reference type is ill-formed. Use reference_wrapper" + ); + static_assert( + conjunction>...>::value, + "A variant containing void is ill-formed." + ); + + //-------------------------------------------------------------------------- + // Public Member Types + //-------------------------------------------------------------------------- + + using base_type = detail::variant_base< + conjunction...>::value, + Types... + >; + using first_type = typename detail::nth_type_t<0,Types...>; + + static constexpr bool is_default_constructible + = bpstd::is_default_constructible::value; + + static constexpr bool is_move_constructible = conjunction< + bpstd::is_move_constructible... + >::value; + + static constexpr bool is_copy_constructible = conjunction< + bpstd::is_copy_constructible... + >::value; + + static constexpr bool is_copy_assignable = conjunction< + bpstd::is_copy_constructible..., + bpstd::is_copy_assignable... + >::value; + + static constexpr bool is_move_assignable = conjunction< + bpstd::is_move_constructible..., + bpstd::is_move_assignable... + >::value; + + static constexpr bool is_nothrow_default_constructible = conjunction< + bpstd::is_nothrow_default_constructible... + >::value; + + static constexpr bool is_nothrow_move_constructible = conjunction< + bpstd::is_nothrow_move_constructible... + >::value; + + static constexpr bool is_nothrow_copy_constructible = conjunction< + bpstd::is_nothrow_copy_constructible... + >::value; + + template + using i_is_in_range = bool_constant<(I < sizeof...(Types))>; + + template + using enable_if_convertible = + enable_if_t< + conjunction< + negation, variant>>, + detail::is_not_in_place>, + detail::has_constructible_alternative, + detail::can_construct_alternative + >::value + >; + + template + using enable_if_convert_assignable = + enable_if_t< + conjunction< + negation, variant>>, + detail::is_not_in_place>, + detail::has_constructible_alternative, + detail::can_construct_alternative, + detail::can_assign_alternative + >::value + >; + + template + using T_j = detail::constructible_alternative_t; + + struct variant_ctor{}; + + //-------------------------------------------------------------------------- + // Constructors + //-------------------------------------------------------------------------- + public: + + // (1) + + /// \brief Default constructor. + /// + /// Constructs a variant holding the value-initialized value of the first + /// alternative (index() is zero). + /// + /// \note This constructor is constexpr if and only if the value + /// initialization of the alternative type T_0 would satisfy the + /// requirements for a constexpr function. + /// + /// \note This overload only participates in overload resolution if + /// std::is_default_constructible_v is true. + constexpr variant(detail::enable_overload_if_t = {}) + noexcept(std::is_nothrow_default_constructible::value); + + // (2) + + /// \brief Copy constructor. + /// + /// If other is not valueless_by_exception, constructs a variant holding + /// the same alternative as other and direct-initializes the contained + /// value with std::get(other). + /// Otherwise, initializes a valueless_by_exception variant. + /// + /// \note This overload only participates in overload resolution if + /// std::is_copy_constructible_v is true for all T_i in Types.... + /// + /// \param other the other variant to copy + variant(detail::enable_overload_if_t other) + noexcept(bpstd::conjunction...>::value); + variant(detail::disable_overload_if_t other) = delete; + + // (3) + + /// \brief Move constructor. + /// + /// If other is not valueless_by_exception, constructs a variant holding + /// the same alternative as other and direct-initializes the contained + /// value with std::get(std::move(other)). + /// Otherwise, initializes a valueless_by_exception variant. + /// + /// \note This overload only participates in overload resolution if + /// std::is_move_constructible_v is true for all T_i in Types... + /// + /// \param other the other variant to move + variant(detail::enable_overload_if_t other) + noexcept(bpstd::conjunction...>::value); + variant(detail::disable_overload_if_t other) = delete; + + // (4) + + /// \brief Converting constructor. + /// + /// Constructs a variant holding the alternative type T_j that would be + /// selected by overload resolution for the expression + /// F(std::forward(t)) if there was an overload of imaginary function + /// F(T_i) for every T_i from Types... in scope at the same time. + /// + /// Direct-initializes the contained value as if by direct + /// non-list-initialization from std::forward(t). + /// + /// \note This overload only participates in overload resolution if + /// - sizeof...(Types) > 0 + /// - std::is_same_v, variant> is false + /// - decay_t is neither a specialization of in_place_type_t + /// nor a specialization of in_place_index_t + /// - std::is_constructible_v is true + /// - and the expression F(std::forward(t)) (with F being the + /// above-mentioned set of imaginary functions) is well formed. + /// + /// \note This constructor is a constexpr constructor if T_j's selected + /// constructor is a constexpr constructor. + /// + /// \param t the value to direct-initialize + template > + constexpr variant(T&& t) + noexcept(bpstd::is_nothrow_constructible::template T_j,T>::value); + + // (5) + + /// \brief Constructs a variant with the specified alternative T and + /// initializes the contained value with the arguments + /// std::forward(args).... + /// + /// \note If T's selected constructor is a constexpr constructor, this + /// constructor is also a constexpr constructor. + /// + /// \note This overload only participates in overload resolution if + /// there is exactly one occurrence of T in Types... and + /// std::is_constructible_v is true + /// + /// \param args the arguments to forward to \p T's constructor + template ::value>> + constexpr explicit variant(in_place_type_t, Args&&... args); + + /// \brief Constructs a variant with the specified alternative T and + /// initializes the contained value with the arguments il, + /// std::forward(args)..... + /// + /// \note If T's selected constructor is a constexpr constructor, this + /// constructor is also a constexpr constructor. + /// + /// \note This overload only participates in overload resolution if + /// there is exactly one occurrence of T in Types... and + /// std::is_constructible_v&, Args...> is true. + /// + /// \param il initializer list of type \p U + /// \param args the arguments to forward to \p T's constructor + template ,Args...>::value>> + constexpr explicit variant(in_place_type_t, + std::initializer_list il, Args&&... args); + + // (7) + + /// \brief Constructs a variant with the alternative T_i specified by + /// the index I and initializes the contained value with the + /// arguments std::forward(args).... + /// + /// \note If T_i's selected constructor is a constexpr constructor, this + /// constructor is also a constexpr constructor. + /// + /// \note This overload only participates in overload resolution if + /// I < sizeof...(Types) and std::is_constructible_v + /// is true + /// + /// \param args the arguments to forward to \p T_i's constructor + template ::value && std::is_constructible,Args...>::value>> + constexpr explicit variant(in_place_index_t, Args&&... args); + + // (8) + + /// \brief Constructs a variant with the alternative T_i specified by + /// the index I and initializes the contained value with the + /// arguments il, std::forward(args).... + /// + /// \note If T_i's selected constructor is a constexpr constructor, this + /// constructor is also a constexpr constructor. + /// + /// \note This overload only participates in overload resolution if + /// I < sizeof...(Types) and + /// std::is_constructible_v&, Args...> + /// is true. + /// + /// \param il initializer list of type \p U + /// \param args the arguments to forward to \p T_i 's constructor + template ::value && std::is_constructible,std::initializer_list,Args...>::value>> + constexpr explicit variant(in_place_index_t, + std::initializer_list il, Args&&... args); + + //-------------------------------------------------------------------------- + + /// \brief Copy assigns the contents of \p other to this + /// + /// If the active variant alternative is the same as \p other , then this + /// will perform an assignment. Otherwise, this destructs the currently + /// active alternative and performs a copy construction. + /// + /// \param other the other variant to copy + variant& operator=(detail::enable_overload_if_t other); + variant& operator=(detail::disable_overload_if_t other) = delete; + + /// \brief Move assigns the contents of \p other to this + /// + /// If the active variant alternative is the same as \p other , then this + /// will perform an assignment. Otherwise, this destructs the currently + /// active alternative and performs a move construction. + /// + /// \param other the other variant to move + variant& operator=(detail::enable_overload_if_t other) + noexcept(conjunction..., + std::is_nothrow_move_assignable...>::value); + variant& operator=(detail::disable_overload_if_t other) = delete; + + template > + variant& operator=(T&& t) + noexcept(std::is_nothrow_assignable::template T_j,T>::value && + std::is_nothrow_constructible::template T_j,T>::value); + + //-------------------------------------------------------------------------- + // Observers + //-------------------------------------------------------------------------- + public: + + /// \brief Returns the zero-based index of the alternative that is + /// currently held by the variant. + /// + /// If the variant is valueless_by_exception, returns variant_npos. + /// + /// \return the zero-based index + constexpr std::size_t index() const noexcept; + + /// \brief Returns false if and only if the variant holds a value + /// + /// \return false if and only if the variant holds a value + constexpr bool valueless_by_exception() const noexcept; + + //-------------------------------------------------------------------------- + // Modifiers + //-------------------------------------------------------------------------- + public: + + /// \brief Creates a new value in-place + /// + /// Equivalent to emplace(std::forward(args)...), where I is the + /// zero-based index of T in Types.... + /// + /// \note This overload only participates in overload resolution if + /// std::is_constructible_v is true, and T + /// occurs exactly once in Types... + /// + /// \tparam T the type to construct + /// \param args the arguments to forward to the constructor of \p T + /// \return reference to constructed element + template ::value>> + T& emplace(Args&&... args); + + /// \brief Creates a new value in-place + /// + /// Equivalent to emplace(il, std::forward(args)...), where I is + /// the zero-based index of T in Types.... + /// + /// \note This overload only participates in overload resolution if + /// std::is_constructible_v, Args...> + /// is true, and \p T occurs exactly once in Types... + /// + /// \tparam T the type to construct + /// \param il an initializer list of entries + /// \param args the arguments to forward to the constructor of \p T + /// \return reference to constructed element + template &,Args...>::value>> + T& emplace(std::initializer_list il, Args&&... args); + + /// \brief Creates a new value in-place + /// + /// First, destroys the currently contained value (if any). + /// Then direct-initializes the contained value as if constructing a + /// value of type T_I with the arguments std::forward(args)... + /// + /// If an exception is thrown, *this may become + /// valueless_by_exception. + /// + /// \note This overload only participates in overload resolution if + /// std::is_constructible_v is true. + /// + /// The behavior is undefined if I is not less than sizeof...(Types). + /// + /// \tparam I the index of the variant alternative to construct + /// \param args the arguments to forward to the constructor of \p T + /// \return reference to constructed element + template ,Args...>::value>> + variant_alternative_t& emplace(Args&&... args); + + /// \brief Creates a new value in-place + /// + /// First, destroys the currently contained value (if any). + /// Then direct-initializes the contained value as if constructing a + /// value of type T_I with the arguments + /// il,std::forward(args)... + /// + /// If an exception is thrown, *this may become + /// valueless_by_exception. + /// + /// \note This overload only participates in overload resolution if + /// std::is_constructible_v Args...> + /// is true. + /// + /// The behavior is undefined if I is not less than sizeof...(Types). + /// + /// \tparam I the index of the variant alternative to construct + /// \param args the arguments to forward to the constructor of \p T + /// \return reference to constructed element + template ,std::initializer_list&,Args...>::value>> + variant_alternative_t& emplace(std::initializer_list il, Args&&... args); + + /// \brief Swaps the contents of this and \p rhs + /// + /// \param rhs the entry to swap with + void swap(variant& rhs) + noexcept(bpstd::conjunction..., + bpstd::is_nothrow_swappable...>::value); + + + //-------------------------------------------------------------------------- + // Private Members + //-------------------------------------------------------------------------- + private: + + static bool alternative_is_nothrow_copy_constructible(std::size_t i) noexcept; + static bool alternative_is_nothrow_move_constructible(std::size_t i) noexcept; + + //-------------------------------------------------------------------------- + // Friend Declarations + //-------------------------------------------------------------------------- + private: + + // 'variant' requires a whole lot of friends, due to most of its API + // consisting of free-functions that access the underlying data. + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator==(const variant&, + const variant&) noexcept; + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator!=(const variant&, + const variant&) noexcept; + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator<(const variant&, + const variant&) noexcept; + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator>(const variant&, + const variant&) noexcept; + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator<=(const variant&, + const variant&) noexcept; + + template + friend BPSTD_CPP14_CONSTEXPR + bool operator>=(const variant&, + const variant&) noexcept; + + template + BPSTD_CPP14_CONSTEXPR + friend detail::variant_visitor_invoke_result_t + visit(Visitor&&, Variant&&); + + template + friend BPSTD_CPP14_CONSTEXPR + variant_alternative_t>& + get(variant&); + + template + friend BPSTD_CPP14_CONSTEXPR + variant_alternative_t>&& + get(variant&&); + + template + friend BPSTD_CPP14_CONSTEXPR + const variant_alternative_t>& + get(const variant&); + + template + friend BPSTD_CPP14_CONSTEXPR + const variant_alternative_t>&& + get(const variant&&); + + template + friend constexpr + add_pointer_t>> + get_if(variant*) noexcept; + + template + friend constexpr + add_pointer_t>> + get_if(const variant*) noexcept; + + }; + + //============================================================================ + // non-member functions : class : variant + //============================================================================ + + //---------------------------------------------------------------------------- + // Comparison + //---------------------------------------------------------------------------- + + template + BPSTD_CPP14_CONSTEXPR + bool operator==(const variant& lhs, + const variant& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR + bool operator!=(const variant& lhs, + const variant& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR + bool operator<(const variant& lhs, + const variant& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR + bool operator>(const variant& lhs, + const variant& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR + bool operator<=(const variant& lhs, + const variant& rhs) noexcept; + template + BPSTD_CPP14_CONSTEXPR + bool operator>=(const variant& lhs, + const variant& rhs) noexcept; + + //---------------------------------------------------------------------------- + // Utilities + //---------------------------------------------------------------------------- + + /// \brief Swaps the contents of \p lhs with \p rhs + /// + /// \param lhs the left contents to swap + /// \param rhs the right contents to swap + template + void swap(variant& lhs, variant& rhs) + noexcept(noexcept(lhs.swap(rhs))); + + //---------------------------------------------------------------------------- + // Value Access + //---------------------------------------------------------------------------- + + /// \brief Visits the variant \p v with the given \p visitor + /// + /// \param visitor the visitor to visit the active entry of \p v + /// \param v the variant to visit + /// \return the result of visiting the variant \p v + template + BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t + visit(Visitor&& visitor, Variant&& v); + + // /// \brief Visits the variants \p variant0 and \p variants + // /// + // /// \param visitor the visitor to visit the active entry of \p v0 + // /// \param variant0 the first variant to visit + // /// \param variants the rest of the variant to visit + // /// \return the result of visiting the variants + template + BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t + visit(Visitor&& visitor, Variant0&& variant0, Variants&&...variants); + + //---------------------------------------------------------------------------- + + /// \brief Checks if the variant v holds the alternative T. + /// + /// The call is ill-formed if T appears more than once in Types... + /// + /// \param v variant to examine + /// \return true if the variant currently holds the alternative T + template + constexpr bool holds_alternative(const variant& v) noexcept; + + //---------------------------------------------------------------------------- + + /// \{ + /// \brief Gets the alternative at index \p I from the variant \p v + /// + /// \tparam I the alternative index + /// \param v the variant + /// \return the alternative at index \p I + template + BPSTD_CPP14_CONSTEXPR variant_alternative_t>& + get(variant& v); + template + BPSTD_CPP14_CONSTEXPR variant_alternative_t>&& + get(variant&& v); + template + BPSTD_CPP14_CONSTEXPR const variant_alternative_t>& + get(const variant& v); + template + BPSTD_CPP14_CONSTEXPR const variant_alternative_t>&& + get(const variant&& v); + /// \} + + //---------------------------------------------------------------------------- + + /// \{ + /// \brief Gets the underlying element of the variant with the specified type + /// + /// \throw bad_variant_access if T is not the active alternative + /// + /// \tparam T the type of the alternative to retrieve + /// \param v the variant to extract the entry from + /// \return the alternative + template + BPSTD_CPP14_CONSTEXPR T& get(variant& v); + template + BPSTD_CPP14_CONSTEXPR T&& get(variant&& v); + template + BPSTD_CPP14_CONSTEXPR const T& get(const variant& v); + template + BPSTD_CPP14_CONSTEXPR const T&& get(const variant&& v); + /// \} + + //---------------------------------------------------------------------------- + + /// \{ + /// \brief Index-based non-throwing accessor + /// + /// If \p pv is not a null pointer and pv->index() == I, returns a + /// pointer to the value stored in the variant pointed to by pv. + /// Otherwise, returns a null pointer value. + /// + /// The call is ill-formed if I is not a valid index in the variant + /// + /// \tparam I the index of the alternative to extract + /// \param pv the pointer to the variant to extract the value from + /// \return pointer to the variant alternative when successful + template + constexpr add_pointer_t>> + get_if(variant* pv) noexcept; + template + constexpr add_pointer_t>> + get_if(const variant* pv) noexcept; + /// \} + + /// \{ + /// \brief Type-based non-throwing accessor + /// + /// Equivalent to the index-based get_if with I being the zero-based + /// index of \p T in Types.... + /// + /// The call is ill-formed if T is not a unique element of Types. + /// + /// \tparam T the alternative type to retrieve + /// \param pv the pointer to the variant to extract the value from + /// \return pointer to the variant alternative when successful + template + constexpr add_pointer_t get_if(variant* pv) noexcept; + template + constexpr add_pointer_t get_if(const variant* pv) noexcept; + /// \} + +} // namespace bpstd + +//============================================================================== +// struct : monostate +//============================================================================== + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator==(monostate, monostate) + noexcept +{ + return true; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator!=(monostate, monostate) + noexcept +{ + return false; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<(monostate, monostate) + noexcept +{ + return false; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>(monostate, monostate) + noexcept +{ + return false; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator<=(monostate, monostate) + noexcept +{ + return true; +} + +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::operator>=(monostate, monostate) + noexcept +{ + return true; +} + +//============================================================================== +// class : bad_variant_access +//============================================================================== + +inline +const char* bpstd::bad_variant_access::what() + const noexcept +{ + return "bad_variant_access"; +} + +//============================================================================== +// class : variant +//============================================================================== + +//------------------------------------------------------------------------------ +// Constructors / Assignment +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(detail::enable_overload_if_t) + noexcept(std::is_nothrow_default_constructible::value) + : base_type{detail::variant_index_tag<0>{}} +{ + +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant::variant(detail::enable_overload_if_t other) + noexcept(bpstd::conjunction...>::value) + : base_type{} +{ + if (other.valueless_by_exception()) { + return; + } + detail::visit_union( + other.base_type::m_index, + detail::variant_copy_construct_visitor{}, + base_type::m_union, + other.base_type::m_union + ); + base_type::m_index = other.base_type::m_index; +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant::variant(detail::enable_overload_if_t other) + noexcept(bpstd::conjunction...>::value) + : base_type{} +{ + if (other.valueless_by_exception()) { + return; + } + detail::visit_union( + other.base_type::m_index, + detail::variant_move_construct_visitor{}, + base_type::m_union, + bpstd::move(other.base_type::m_union) + ); + base_type::m_index = other.base_type::m_index; +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(T&& t) + noexcept(bpstd::is_nothrow_constructible::template T_j,T>::value) + : base_type{ + detail::variant_index_tag::value>{}, + bpstd::forward(t) + } +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(in_place_type_t, Args&&... args) + : base_type{ + detail::variant_index_tag::value>{}, + bpstd::forward(args)... + } +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(in_place_type_t, std::initializer_list il, Args&&... args) + : base_type{ + detail::variant_index_tag::value>{}, + il, bpstd::forward(args)... + } +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(in_place_index_t, Args&&... args) + : base_type{ + detail::variant_index_tag{}, + bpstd::forward(args)... + } +{ + +} + +template +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::variant::variant(in_place_index_t, std::initializer_list il, Args&&... args) + : base_type{ + detail::variant_index_tag{}, + il, bpstd::forward(args)... + } +{ + +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant& + bpstd::variant::operator=(detail::enable_overload_if_t other) +{ + if (other.valueless_by_exception()) { + base_type::destroy_active_object(); + return (*this); + } + + if (other.base_type::m_index == base_type::m_index) { + detail::visit_union( + other.base_type::m_index, + detail::variant_copy_assign_visitor{}, + base_type::m_union, + other.base_type::m_union + ); + return (*this); + } + + const auto should_copy = + alternative_is_nothrow_copy_constructible(other.index()) || + !alternative_is_nothrow_move_constructible(other.index()); + + if (should_copy) { + base_type::destroy_active_object(); + detail::visit_union( + other.base_type::m_index, + detail::variant_copy_construct_visitor{}, + base_type::m_union, + other.base_type::m_union + ); + base_type::m_index = other.base_type::m_index; + return (*this); + } + + return this->operator=(variant(other)); +} + +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant& + bpstd::variant::operator=(detail::enable_overload_if_t other) + noexcept(conjunction..., + std::is_nothrow_move_assignable...>::value) +{ + if (other.valueless_by_exception()) { + base_type::destroy_active_object(); + return (*this); + } + + if (other.base_type::m_index == base_type::m_index) { + detail::visit_union( + other.base_type::m_index, + detail::variant_move_assign_visitor{}, + base_type::m_union, + bpstd::move(other.base_type::m_union) + ); + return (*this); + } + + base_type::destroy_active_object(); + detail::visit_union( + other.base_type::m_index, + detail::variant_move_construct_visitor{}, + base_type::m_union, + bpstd::move(other.base_type::m_union) + ); + base_type::m_index = other.base_type::m_index; + + return (*this); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant& bpstd::variant::operator=(T&& t) + noexcept(std::is_nothrow_assignable::template T_j,T>::value && + std::is_nothrow_constructible::template T_j,T>::value) +{ + static constexpr auto index = detail::index_of_constructible_alternative::value; + + using type = detail::constructible_alternative_t; + + if (base_type::m_index == index) { + detail::visit_union( + base_type::m_index, + detail::variant_assign_visitor{bpstd::forward(t)}, + base_type::m_union + ); + return (*this); + } + + const auto should_emplace = + alternative_is_nothrow_copy_constructible(index) || + !alternative_is_nothrow_move_constructible(index); + + if (should_emplace) { + emplace(bpstd::forward(t)); + return (*this); + } + + return this->operator=(variant(bpstd::forward(t))); +} + +//------------------------------------------------------------------------------ +// Observers +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +std::size_t bpstd::variant::index() + const noexcept +{ + return base_type::m_index; +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::variant::valueless_by_exception() + const noexcept +{ + return index() == variant_npos; +} + +//------------------------------------------------------------------------------ +// Modifiers +//------------------------------------------------------------------------------ + +template +template +inline BPSTD_INLINE_VISIBILITY +T& bpstd::variant::emplace(Args&&...args) +{ + using index_type = detail::index_from; + + static_assert(index_type::value != variant_npos, "T must be a valid alternative"); + + return emplace(bpstd::forward(args)...); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +T& bpstd::variant::emplace(std::initializer_list il, Args&&...args) +{ + using index_type = detail::index_from; + + static_assert(index_type::value != variant_npos, "T must be a valid alternative"); + + return emplace(il, bpstd::forward(args)...); +} + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant_alternative_t>& + bpstd::variant::emplace(Args&&...args) +{ + using type = detail::nth_type_t; + + base_type::destroy_active_object(); + + using tuple_type = decltype(std::forward_as_tuple(bpstd::forward(args)...)); + + auto visitor = detail::variant_emplace_visitor( + std::forward_as_tuple(bpstd::forward(args)...) + ); + + detail::visit_union(I, visitor, base_type::m_union); + base_type::m_index = I; + + return detail::union_get(base_type::m_union); +} + + +template +template +inline BPSTD_INLINE_VISIBILITY +bpstd::variant_alternative_t>& + bpstd::variant::emplace(std::initializer_list il, Args&&... args) +{ + using type = detail::nth_type_t; + + base_type::destroy_active_object(); + + using tuple_type = decltype(std::forward_as_tuple(il, bpstd::forward(args)...)); + + auto visitor = detail::variant_emplace_visitor( + std::forward_as_tuple(il, bpstd::forward(args)...) + ); + + detail::visit_union(I, visitor, base_type::m_union); + base_type::m_index = I; + + return detail::union_get(base_type::m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::variant::swap(variant& other) + noexcept(bpstd::conjunction..., + bpstd::is_nothrow_swappable...>::value) + +{ + if (valueless_by_exception() && other.valueless_by_exception()) { + return; + } + + if (base_type::m_index == other.base_type::m_index) { + detail::visit_union( + base_type::m_index, + detail::variant_swap_visitor{}, + base_type::m_union, + other.m_union + ); + } else { + auto temp = bpstd::move(*this); + *this = bpstd::move(other); + other = bpstd::move(temp); + } +} + +template +inline BPSTD_INLINE_VISIBILITY +bool bpstd::variant::alternative_is_nothrow_copy_constructible(std::size_t i) + noexcept +{ + const bool alternatives[]{bpstd::is_nothrow_copy_constructible::value...}; + + return alternatives[i]; +} + +template +inline BPSTD_INLINE_VISIBILITY +bool bpstd::variant::alternative_is_nothrow_move_constructible(std::size_t i) + noexcept +{ + const bool alternatives[]{bpstd::is_nothrow_move_constructible::value...}; + + return alternatives[i]; +} + +//============================================================================== +// non-member functions : class : variant +//============================================================================== + +//------------------------------------------------------------------------------ +// Comparisons +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator==(const variant& lhs, + const variant& rhs) + noexcept +{ + if (lhs.index() != rhs.index()) { + return false; + } + if (lhs.valueless_by_exception()) { + return true; + } + return detail::visit_union(lhs.index(), equal_to<>{}, lhs.m_union, rhs.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator!=(const variant& lhs, + const variant& rhs) + noexcept +{ + if (lhs.index() != rhs.index()) { + return true; + } + if (lhs.valueless_by_exception()) { + return false; + } + return detail::visit_union(lhs.index(), not_equal_to<>{}, lhs.m_union, rhs.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator<(const variant& lhs, + const variant& rhs) + noexcept +{ + if (rhs.valueless_by_exception()) { + return false; + } + if (lhs.valueless_by_exception()) { + return true; + } + if (lhs.index() < rhs.index()) { + return true; + } + if (lhs.index() > rhs.index()) { + return false; + } + return detail::visit_union(lhs.index(), less<>{}, lhs.m_union, rhs.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator>(const variant& lhs, + const variant& rhs) + noexcept +{ + if (lhs.valueless_by_exception()) { + return false; + } + if (rhs.valueless_by_exception()) { + return true; + } + if (lhs.index() > rhs.index()) { + return true; + } + if (lhs.index() < rhs.index()) { + return false; + } + return detail::visit_union(lhs.index(), greater<>{}, lhs.m_union, rhs.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator<=(const variant& lhs, + const variant& rhs) + noexcept +{ + if (lhs.valueless_by_exception()) { + return true; + } + if (rhs.valueless_by_exception()) { + return false; + } + if (lhs.index() < rhs.index()) { + return true; + } + if (lhs.index() > rhs.index()) { + return false; + } + return detail::visit_union(lhs.index(), less_equal<>{}, lhs.m_union, rhs.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bool bpstd::operator>=(const variant& lhs, + const variant& rhs) + noexcept +{ + if (rhs.valueless_by_exception()) { + return true; + } + if (lhs.valueless_by_exception()) { + return false; + } + if (lhs.index() > rhs.index()) { + return true; + } + if (lhs.index() < rhs.index()) { + return false; + } + return detail::visit_union(lhs.index(), greater_equal<>{}, lhs.m_union, rhs.m_union); +} + +//------------------------------------------------------------------------------ +// Utilities +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY +void bpstd::swap(variant& lhs, variant& rhs) + noexcept(noexcept(lhs.swap(rhs))) +{ + lhs.swap(rhs); +} + +//------------------------------------------------------------------------------ +// Value Access +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::detail::variant_visitor_invoke_result_t + bpstd::visit(Visitor&& visitor, Variant&& v) +{ + using union_type = detail::match_cvref_t; + + if (v.valueless_by_exception()) { + throw bad_variant_access{}; + } + + return detail::visit_union( + v.index(), + bpstd::forward(visitor), + static_cast(v.m_union) + ); +} + +namespace bpstd { namespace detail { + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool are_any_valueless_by_exception(const Variant0& v0, const Variants&...vs) +{ + return v0.valueless_by_exception() || are_any_valueless_by_exception(vs...); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool are_any_valueless_by_exception(const Variant0& v0) +{ + return v0.valueless_by_exception(); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +std::tuple tuple_push_back_aux(std::tuple& args, T&& v, index_sequence) +{ + (void) args; + return std::forward_as_tuple(std::get(bpstd::move(args))..., bpstd::forward(v)); +} + +// Appends an element to a forwarding tuple +// Returns with '&&' to reference-collapse returned types +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +std::tuple tuple_push_back(std::tuple& args, T&& t) +{ + static_assert( + conjunction...,true_type>::value, + "'args' must be a forwarding tuple'" + ); + // return std::tuple_cat(args, std::forward_as_tuple(std::forward(t))); + return tuple_push_back_aux(args, bpstd::forward(t), index_sequence_for{}); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +std::tuple tuple_pop_front_aux(std::tuple& args, index_sequence<0, Idxs...>) +{ + (void) args; + return std::forward_as_tuple(std::get(bpstd::move(args))...); +} + +// Removes the front element of a forwarding tuple +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +std::tuple tuple_pop_front(std::tuple& args) +{ + static_assert( + conjunction,is_reference...>::value, + "'args' must be a forwarding tuple'" + ); + + return tuple_pop_front_aux(args, index_sequence_for{}); +} + +template +class multi_variant_visitor; + +template +BPSTD_CPP14_CONSTEXPR +multi_variant_visitor, remove_cvref_t> + make_multi_visitor(Visitor&& vistior, Variants&& variants, Arguments&& args); + +template +class multi_variant_visitor, std::tuple> +{ + static_assert( + conjunction, is_reference...>::value, + "All Variants must be captured by reference" + ); + static_assert( + conjunction...,true_type>::value, + "All arguments must be captured by reference" + ); + +public: + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + multi_variant_visitor(UVisitor&& visitor, UVariants&& variants, Arguments&& args) + : m_visitor(bpstd::forward(visitor)), + m_variants(bpstd::forward(variants)), + m_args(bpstd::forward(args)) + { + + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + Return operator()(T&& v) + { + // static_assert(is_reference::value, "T should always be a reference type"); + + return visit( + detail::make_multi_visitor( + bpstd::forward(m_visitor), + tuple_pop_front(m_variants), + tuple_push_back(m_args, bpstd::forward(v)) + ), + std::get<0>(bpstd::move(m_variants)) // 'move' used for reference collapse + ); + } + +private: + + Visitor m_visitor; + std::tuple m_variants; + std::tuple m_args; +}; + +template +class multi_variant_visitor,std::tuple> +{ + static_assert( + conjunction...,true_type>::value, + "All arguments must be captured by reference" + ); + +public: + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + multi_variant_visitor(UVisitor&& visitor, Variants&&, Arguments&& args) + : m_visitor(bpstd::forward(visitor)), + m_args(bpstd::forward(args)) + { + + } + + template + inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR + Return operator()(T&& v) + { + return apply( + bpstd::forward(m_visitor), + tuple_push_back(m_args, bpstd::forward(v)) + ); + } + +private: + + Visitor m_visitor; + std::tuple m_args; +}; + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +multi_variant_visitor, remove_cvref_t> + make_multi_visitor(Visitor&& visitor, Variants&& variants, Arguments&& args) +{ + return { + bpstd::forward(visitor), + bpstd::forward(variants), + bpstd::forward(args) + }; +} + +}} // namespace bpstd::detail + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::detail::variant_visitor_invoke_result_t + bpstd::visit(Visitor&& visitor, Variant0&& variant0, Variants&&...variants) +{ + using type = bpstd::detail::variant_visitor_invoke_result_t; + + if (detail::are_any_valueless_by_exception(variant0, variants...)) { + throw bad_variant_access{}; + } + + return visit( + detail::make_multi_visitor( + bpstd::forward(visitor), + std::forward_as_tuple(bpstd::forward(variants)...), + std::make_tuple() + ), + bpstd::forward(variant0) + ); + +} + + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bool bpstd::holds_alternative(const variant& v) + noexcept +{ + return detail::index_from::value == v.index(); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::variant_alternative_t>& + bpstd::get(variant& v) +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + if (v.index() != I) { + throw bad_variant_access{}; + } + return detail::union_get(v.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +bpstd::variant_alternative_t>&& + bpstd::get(variant&& v) +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + if (v.index() != I) { + throw bad_variant_access{}; + } + return bpstd::move(detail::union_get(v.m_union)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const bpstd::variant_alternative_t>& + bpstd::get(const variant& v) +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + if (v.index() != I) { + throw bad_variant_access{}; + } + return detail::union_get(v.m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const bpstd::variant_alternative_t>&& + bpstd::get(const variant&& v) +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + if (v.index() != I) { + throw bad_variant_access{}; + } + return bpstd::move(detail::union_get(v.m_union)); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T& bpstd::get(variant& v) +{ + using index_type = detail::index_from; + + return get(v); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +T&& bpstd::get(variant&& v) +{ + using index_type = detail::index_from; + + return get(bpstd::move(v)); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const T& bpstd::get(const variant& v) +{ + using index_type = detail::index_from; + + return get(v); +} + +template +inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR +const T&& bpstd::get(const variant&& v) +{ + using index_type = detail::index_from; + + return get(bpstd::move(v)); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::add_pointer_t>> + bpstd::get_if(variant* pv) + noexcept +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + return (pv == nullptr || I != pv->index()) + ? nullptr + : &detail::union_get(pv->m_union); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::add_pointer_t>> + bpstd::get_if(const variant* pv) + noexcept +{ + static_assert( + I < sizeof...(Types), + "I is not a valid index into the variant" + ); + + return (pv == nullptr || I != pv->index()) + ? nullptr + : &detail::union_get(pv->m_union); +} + +//------------------------------------------------------------------------------ + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::add_pointer_t + bpstd::get_if(variant* pv) + noexcept +{ + using index_type = detail::index_from; + + return get_if(pv); +} + +template +inline BPSTD_INLINE_VISIBILITY constexpr +bpstd::add_pointer_t + bpstd::get_if(const variant* pv) + noexcept +{ + using index_type = detail::index_from; + + return get_if(pv); +} + +BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE + +#endif /* BPSTD_VARIANT_HPP */ diff --git a/src/libs/vmisc/vmisc.pri b/src/libs/vmisc/vmisc.pri index 2c1e44094..56429fc5c 100644 --- a/src/libs/vmisc/vmisc.pri +++ b/src/libs/vmisc/vmisc.pri @@ -26,6 +26,33 @@ contains(DEFINES, APPIMAGE) { } HEADERS += \ + $$PWD/bpstd/any.hpp \ + $$PWD/bpstd/chrono.hpp \ + $$PWD/bpstd/complex.hpp \ + $$PWD/bpstd/cstddef.hpp \ + $$PWD/bpstd/detail/config.hpp \ + $$PWD/bpstd/detail/enable_overload.hpp \ + $$PWD/bpstd/detail/invoke.hpp \ + $$PWD/bpstd/detail/move.hpp \ + $$PWD/bpstd/detail/nth_type.hpp \ + $$PWD/bpstd/detail/proxy_iterator.hpp \ + $$PWD/bpstd/detail/variant_base.hpp \ + $$PWD/bpstd/detail/variant_fwds.hpp \ + $$PWD/bpstd/detail/variant_traits.hpp \ + $$PWD/bpstd/detail/variant_union.hpp \ + $$PWD/bpstd/detail/variant_visitors.hpp \ + $$PWD/bpstd/exception.hpp \ + $$PWD/bpstd/functional.hpp \ + $$PWD/bpstd/iterator.hpp \ + $$PWD/bpstd/memory.hpp \ + $$PWD/bpstd/optional.hpp \ + $$PWD/bpstd/span.hpp \ + $$PWD/bpstd/string.hpp \ + $$PWD/bpstd/string_view.hpp \ + $$PWD/bpstd/tuple.hpp \ + $$PWD/bpstd/type_traits.hpp \ + $$PWD/bpstd/utility.hpp \ + $$PWD/bpstd/variant.hpp \ $$PWD/compatibility.h \ $$PWD/lambdaconstants.h \ $$PWD/stable.h \