Backport std::chrono_literals to C++11.

This commit is contained in:
Roman Telezhynskyi 2022-09-08 16:43:21 +03:00
parent fd173c81cd
commit 8a902d8f66
34 changed files with 13646 additions and 29 deletions

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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.

View File

@ -0,0 +1,935 @@
////////////////////////////////////////////////////////////////////////////////
/// \file any.hpp
///
/// \brief This header provides definitions from the C++ header <any>
////////////////////////////////////////////////////////////////////////////////
/*
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 <typeinfo> // std::bad_cast, std::type_info
#include <initializer_list> // std::initializer_list
#include <new> // placement-new
#include <cassert> // 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<typename ValueType,
typename=enable_if_t<!is_same<decay_t<ValueType>,any>::value &&
is_copy_constructible<decay_t<ValueType>>::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<typename ValueType, typename...Args,
typename=enable_if_t<is_constructible<decay_t<ValueType>,Args...>::value &&
is_copy_constructible<decay_t<ValueType>>::value>>
explicit any(in_place_type_t<ValueType>, 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<typename ValueType, typename U, typename...Args,
typename=enable_if_t<is_constructible<decay_t<ValueType>,std::initializer_list<U>,Args...>::value &&
is_copy_constructible<decay_t<ValueType>>::value>>
explicit any(in_place_type_t<ValueType>,
std::initializer_list<U> 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<typename ValueType,
typename=enable_if_t<!is_same<decay_t<ValueType>,any>::value &&
is_copy_constructible<decay_t<ValueType>>::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<typename ValueType, typename...Args,
typename=enable_if_t<is_constructible<decay_t<ValueType>,Args...>::value &&
is_copy_constructible<decay_t<ValueType>>::value>>
decay_t<ValueType>& emplace(Args&&...args);
template<typename ValueType, typename U, typename...Args,
typename=enable_if_t<is_constructible<decay_t<ValueType>,std::initializer_list<U>,Args...>::value &&
is_copy_constructible<decay_t<ValueType>>::value>>
decay_t<ValueType>& emplace(std::initializer_list<U> 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<buffer_size,buffer_align>::type;
union storage
{
internal_buffer internal;
void* external;
};
//--------------------------------------------------------------------------
// trait to determine if internal storage is required
template<typename T>
using requires_internal_storage = bool_constant<
(sizeof(T) <= buffer_size) &&
((buffer_align % alignof(T)) == 0) &&
is_nothrow_move_constructible<T>::value
>;
//-----------------------------------------------------------------------
template<typename T>
struct internal_storage_handler;
template<typename T>
struct external_storage_handler;
template<typename T>
using storage_handler = conditional_t<
requires_internal_storage<T>::value,
internal_storage_handler<T>,
external_storage_handler<T>
>;
//-----------------------------------------------------------------------
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<typename T>
friend T* any_cast(any*) noexcept;
template<typename T>
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<typename T>
T any_cast(any& operand);
template<typename T>
T any_cast(any&& operand);
template<typename T>
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<typename T>
T* any_cast(any* operand) noexcept;
template<typename T>
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<typename T>
struct bpstd::any::internal_storage_handler
{
template<typename...Args>
static T* construct(storage& s, Args&&...args);
template<typename U, typename...Args>
static T* construct(storage& s, std::initializer_list<U> 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<typename T>
template<typename...Args>
inline BPSTD_INLINE_VISIBILITY
T* bpstd::any::internal_storage_handler<T>
::construct(storage& s, Args&&...args)
{
return ::new(&s.internal) T(bpstd::forward<Args>(args)...);
}
template<typename T>
template<typename U, typename...Args>
inline BPSTD_INLINE_VISIBILITY
T* bpstd::any::internal_storage_handler<T>
::construct(storage& s, std::initializer_list<U> il, Args&&...args)
{
return ::new(&s.internal) T(il, bpstd::forward<Args>(args)...);
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
void bpstd::any::internal_storage_handler<T>
::destroy(storage& s)
{
auto* t = static_cast<T*>(static_cast<void*>(&s.internal));
t->~T();
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
const void* bpstd::any::internal_storage_handler<T>
::handle(operation op,
const storage* self,
const storage* other)
{
switch (op)
{
case operation::destroy:
{
assert(self != nullptr);
BPSTD_UNUSED(other);
destroy(const_cast<storage&>(*self));
break;
}
case operation::copy:
{
assert(self != nullptr);
assert(other != nullptr);
// Copy construct from the internal storage
const auto* p = reinterpret_cast<const T*>(&other->internal);
construct( const_cast<storage&>(*self), *p);
break;
}
case operation::move:
{
assert(self != nullptr);
assert(other != nullptr);
// Move construct from the internal storage. '
const auto* p = reinterpret_cast<const T*>(&other->internal);
construct(const_cast<storage&>(*self), bpstd::move(*const_cast<T*>(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<const T*>(&self->internal);
return static_cast<const void*>(p);
}
case operation::type:
{
BPSTD_UNUSED(self);
BPSTD_UNUSED(other);
return static_cast<const void*>(&typeid(T));
}
}
return nullptr;
}
//=============================================================================
// class : any::external_storage_handler
//=============================================================================
template<typename T>
struct bpstd::any::external_storage_handler
{
template<typename...Args>
static T* construct(storage& s, Args&&...args);
template<typename U, typename...Args>
static T* construct(storage& s, std::initializer_list<U> 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<typename T>
template<typename...Args>
inline BPSTD_INLINE_VISIBILITY
T* bpstd::any::external_storage_handler<T>
::construct(storage& s, Args&&...args)
{
s.external = new T(bpstd::forward<Args>(args)...);
return static_cast<T*>(s.external);
}
template<typename T>
template<typename U, typename...Args>
inline BPSTD_INLINE_VISIBILITY
T* bpstd::any::external_storage_handler<T>
::construct(storage& s, std::initializer_list<U> il, Args&&...args)
{
s.external = new T(il, bpstd::forward<Args>(args)...);
return static_cast<T*>(s.external);
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
void bpstd::any::external_storage_handler<T>
::destroy(storage& s)
{
delete static_cast<T*>(s.external);
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
const void* bpstd::any::external_storage_handler<T>
::handle( operation op,
const storage* self,
const storage* other )
{
switch (op)
{
case operation::destroy:
{
assert(self != nullptr);
BPSTD_UNUSED(other);
destroy(const_cast<storage&>(*self));
break;
}
case operation::copy:
{
assert(self != nullptr);
assert(other != nullptr);
// Copy construct from the internal storage
construct( const_cast<storage&>(*self),
*static_cast<const T*>(other->external));
break;
}
case operation::move:
{
BPSTD_UNUSED(self != nullptr);
assert(other != nullptr);
const auto p = static_cast<const T*>(other->external);
// Move construct from the internal storage. '
construct(const_cast<storage&>(*self), bpstd::move(*const_cast<T*>(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<typename ValueType, typename>
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<decay_t<ValueType>>;
handler_type::construct(m_storage, bpstd::forward<ValueType>(value));
m_storage_handler = &handler_type::handle;
}
template<typename ValueType, typename...Args, typename>
inline BPSTD_INLINE_VISIBILITY
bpstd::any::any(in_place_type_t<ValueType>, Args&&...args)
: m_storage{},
m_storage_handler{nullptr}
{
// Set handler after constructing, in case of exception
using handler_type = storage_handler<decay_t<ValueType>>;
handler_type::construct(m_storage, bpstd::forward<Args>(args)...);
m_storage_handler = &handler_type::handle;
}
template<typename ValueType, typename U, typename...Args, typename>
inline BPSTD_INLINE_VISIBILITY
bpstd::any::any(in_place_type_t<ValueType>,
std::initializer_list<U> il,
Args&&...args)
: m_storage{},
m_storage_handler{nullptr}
{
// Set handler after constructing, in case of exception
using handler_type = storage_handler<decay_t<ValueType>>;
handler_type::construct(m_storage, il, bpstd::forward<Args>(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<typename ValueType, typename>
inline BPSTD_INLINE_VISIBILITY
bpstd::any& bpstd::any::operator=(ValueType&& value)
{
using handler_type = storage_handler<decay_t<ValueType>>;
reset();
handler_type::construct(m_storage, bpstd::forward<ValueType>(value));
m_storage_handler = &handler_type::handle;
return (*this);
}
//-----------------------------------------------------------------------------
// Modifiers
//-----------------------------------------------------------------------------
template<typename ValueType, typename...Args, typename>
inline BPSTD_INLINE_VISIBILITY
bpstd::decay_t<ValueType>&
bpstd::any::emplace(Args&&...args)
{
using handler_type = storage_handler<decay_t<ValueType>>;
reset();
auto& result = *handler_type::construct(m_storage,
bpstd::forward<Args>(args)...);
m_storage_handler = &handler_type::handle;
return result;
}
template<typename ValueType, typename U, typename...Args, typename>
inline BPSTD_INLINE_VISIBILITY
bpstd::decay_t<ValueType>&
bpstd::any::emplace(std::initializer_list<U> il,
Args&&...args)
{
using handler_type = storage_handler<decay_t<ValueType>>;
reset();
auto& result = *handler_type::construct(m_storage,
il,
bpstd::forward<Args>(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<const std::type_info*>(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<typename T>
inline BPSTD_INLINE_VISIBILITY
T bpstd::any_cast(any& operand)
{
using underlying_type = remove_cvref_t<T>;
static_assert(
is_constructible<T, underlying_type&>::value,
"A program is ill-formed if T is not constructible from U&"
);
auto* p = any_cast<underlying_type>(&operand);
if (p == nullptr) {
throw bad_any_cast{};
}
return static_cast<T>(*p);
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
T bpstd::any_cast(any&& operand)
{
using underlying_type = remove_cvref_t<T>;
static_assert(
is_constructible<T, underlying_type>::value,
"A program is ill-formed if T is not constructible from U"
);
auto* p = any_cast<underlying_type>(&operand);
if (p == nullptr) {
throw bad_any_cast{};
}
return static_cast<T>(bpstd::move(*p));
}
template<typename T>
inline BPSTD_INLINE_VISIBILITY
T bpstd::any_cast(const any& operand)
{
using underlying_type = remove_cvref_t<T>;
static_assert(
is_constructible<T, const underlying_type&>::value,
"A program is ill-formed if T is not constructible from const U&"
);
const auto* p = any_cast<underlying_type>(&operand);
if (p == nullptr) {
throw bad_any_cast{};
}
return static_cast<T>(*p);
}
template<typename T>
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<T*>(static_cast<const T*>(p));
}
template<typename T>
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<const T*>(p);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_ANY_HPP */

View File

@ -0,0 +1,438 @@
////////////////////////////////////////////////////////////////////////////////
/// \file chrono.hpp
///
/// \brief This header provides definitions from the C++ header <chrono>
////////////////////////////////////////////////////////////////////////////////
/*
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 <chrono> // std::chrono::duration, std::chrono::system_clock, etc
#include <cstdint> // std::int32_t
#if __cplusplus < 201402L
#include <QtGlobal>
#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 <typename Rep, typename Period = std::ratio<1>>
using duration = std::chrono::duration<Rep,Period>;
template <typename Clock, typename Duration = typename Clock::duration>
using time_point = std::chrono::time_point<Clock, Duration>;
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<std::int32_t, std::ratio<86400>>;
using weeks = std::chrono::duration<std::int32_t, std::ratio<604800>>;
using months = std::chrono::duration<std::int32_t, std::ratio<2629746>>;
using years = std::chrono::duration<std::int32_t, std::ratio<31556952>>;
using steady_clock = std::chrono::steady_clock;
using system_clock = std::chrono::system_clock;
template <typename Duration>
using sys_time = time_point<system_clock, Duration>;
using sys_seconds = sys_time<seconds>;
using sys_days = sys_time<days>;
} // 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<double, std::ratio<3600,1>>;
#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<double, std::ratio<3600,1>>;
QT_WARNING_POP
#endif
constexpr auto operator""_min(unsigned long long x) -> chrono::minutes;
constexpr auto operator""_min(long double x) -> chrono::duration<double, std::ratio<60>>;
#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<double, std::ratio<60>>;
QT_WARNING_POP
#endif
constexpr auto operator""_s(unsigned long long x) -> chrono::seconds;
constexpr auto operator""_s(long double x) -> chrono::duration<double>;
#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<double>;
QT_WARNING_POP
#endif
constexpr auto operator""_ms(unsigned long long x) -> chrono::milliseconds;
constexpr auto operator""_ms(long double x) -> chrono::duration<double, std::milli>;
#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<double, std::milli>;
QT_WARNING_POP
#endif
constexpr auto operator""_us(unsigned long long x) -> chrono::microseconds;
constexpr auto operator""_us(long double x) -> chrono::duration<double, std::micro>;
#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<double, std::micro>;
QT_WARNING_POP
#endif
constexpr auto operator""_ns(unsigned long long x) -> chrono::nanoseconds;
constexpr auto operator""_ns(long double x) -> chrono::duration<double, std::nano>;
#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<double, std::nano>;
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<double, std::ratio<3600,1>>
{
return chrono::duration<double, std::ratio<3600,1>>{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<double, std::ratio<3600,1>>
{
return chrono::duration<double, std::ratio<3600,1>>{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<double, std::ratio<60>>
{
return chrono::duration<double, std::ratio<60>>{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<double, std::ratio<60>>
{
return chrono::duration<double, std::ratio<60>>{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<double>
{
return chrono::duration<double>{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<double>
{
return chrono::duration<double>{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<double, std::milli>
{
return chrono::duration<double, std::milli>{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<double, std::milli>
{
return chrono::duration<double, std::milli>{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<double, std::micro>
{
return chrono::duration<double, std::micro>{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<double, std::micro>
{
return chrono::duration<double, std::micro>{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<double, std::nano>
{
return chrono::duration<double, std::nano>{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<double, std::nano>
{
return chrono::duration<double, std::nano>{x};
}
QT_WARNING_POP
#endif
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_CHRONO_HPP */

View File

@ -0,0 +1,122 @@
////////////////////////////////////////////////////////////////////////////////
/// \file complex.hpp
///
/// \brief This header provides definitions from the C++ header <complex>
////////////////////////////////////////////////////////////////////////////////
/*
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 <complex>
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
//============================================================================
// class : complex
//============================================================================
template <typename T>
using complex = std::complex<T>;
//============================================================================
// literals : class : complex
//============================================================================
inline namespace literals {
inline namespace complex_literals {
constexpr complex<long double> operator""_il(long double i) noexcept;
constexpr complex<long double> operator""_il(unsigned long long i) noexcept;
constexpr complex<double> operator""_i(long double i) noexcept;
constexpr complex<double> operator""_i(unsigned long long i) noexcept;
constexpr complex<float> operator""_if(long double i) noexcept;
constexpr complex<float> operator""_if(unsigned long long i) noexcept;
} // namespace complex_literals
} // namespace literals
} // namespace bpstd
//==============================================================================
// literals : class : complex
//==============================================================================
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<long double>
bpstd::literals::complex_literals::operator""_il(long double i)
noexcept
{
return complex<long double>{0, i};
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<long double>
bpstd::literals::complex_literals::operator""_il(unsigned long long i)
noexcept
{
return complex<long double>{0, static_cast<long double>(i)};
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<double>
bpstd::literals::complex_literals::operator""_i(long double i)
noexcept
{
return complex<double>{0, static_cast<double>(i)};
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<double>
bpstd::literals::complex_literals::operator""_i(unsigned long long i)
noexcept
{
return complex<double>{0, static_cast<double>(i)};
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<float>
bpstd::literals::complex_literals::operator""_if(long double i)
noexcept
{
return complex<float>{0, static_cast<float>(i)};
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::complex<float>
bpstd::literals::complex_literals::operator""_if(unsigned long long i)
noexcept
{
return complex<float>{0, static_cast<float>(i)};
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_COMPLEX_HPP */

View File

@ -0,0 +1,258 @@
////////////////////////////////////////////////////////////////////////////////
/// \file cstddef.hpp
///
/// \brief This header provides definitions from the C++ header <cstddef>
////////////////////////////////////////////////////////////////////////////////
/*
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 <type_traits> // std::is_integral
#include <cstddef> // __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 <typename Integer,
typename = enable_if_t<std::is_integral<Integer>::value>>
constexpr byte operator<<(byte b, Integer shift) noexcept;
template <typename Integer,
typename = enable_if_t<std::is_integral<Integer>::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 <typename Integer,
typename = enable_if_t<std::is_integral<Integer>::value>>
BPSTD_CPP14_CONSTEXPR byte& operator<<=(byte& b, Integer shift) noexcept;
template <typename Integer,
typename = enable_if_t<std::is_integral<Integer>::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 <typename Integer,
typename = enable_if_t<std::is_integral<Integer>::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 <typename Integer, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator<<(byte b, Integer shift)
noexcept
{
return static_cast<byte>(static_cast<unsigned char>(b) << shift);
}
template <typename Integer, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator>>(byte b, Integer shift)
noexcept
{
return static_cast<byte>(static_cast<unsigned char>(b) >> shift);
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator|(byte lhs, byte rhs)
noexcept
{
return static_cast<byte>(
static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs)
);
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator&(byte lhs, byte rhs)
noexcept
{
return static_cast<byte>(
static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs)
);
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator^(byte lhs, byte rhs)
noexcept
{
return static_cast<byte>(
static_cast<unsigned char>(lhs) ^ static_cast<unsigned char>(rhs)
);
}
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::byte bpstd::operator~(byte b)
noexcept
{
return static_cast<byte>(~static_cast<unsigned char>(b));
}
//------------------------------------------------------------------------------
// Compound Bitwise Operators
//------------------------------------------------------------------------------
template <typename Integer, typename>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::byte& bpstd::operator<<=(byte& b, Integer shift)
noexcept
{
return b = static_cast<byte>(static_cast<unsigned char>(b) << shift);
}
template <typename Integer, typename>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::byte& bpstd::operator>>=(byte& b, Integer shift)
noexcept
{
return b = static_cast<byte>(static_cast<unsigned char>(b) >> shift);
}
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::byte& bpstd::operator|=(byte& lhs, byte rhs)
noexcept
{
return lhs = static_cast<byte>(
static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs)
);
}
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::byte& bpstd::operator&=(byte& lhs, byte rhs)
noexcept
{
return lhs = static_cast<byte>(
static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs)
);
}
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::byte& bpstd::operator^=(byte& lhs, byte rhs)
noexcept
{
return lhs = static_cast<byte>(
static_cast<unsigned char>(lhs) ^ static_cast<unsigned char>(rhs)
);
}
#endif // BPSTD_USE_STD_BYTE
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename Integer, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
Integer bpstd::to_integer(byte b)
noexcept
{
return static_cast<Integer>(b);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_CSTDDEF_HPP */

View File

@ -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<void>(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 */

View File

@ -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 <bool b, typename T>
struct enable_overload_if
{
using type = T;
};
template <typename T>
struct enable_overload_if<false,T>
{
class type{ type() = delete; ~type() = delete; };
};
template <bool B, typename T>
using enable_overload_if_t = typename enable_overload_if<B,T>::type;
/// \brief Inverse of enable_overload_if
template <bool B, typename T>
using disable_overload_if = enable_overload_if<!B,T>;
/// \brief Convenience alias to retrieve the ::type member of
/// disable_overload_if
template <bool B, typename T>
using disable_overload_if_t = typename disable_overload_if<B,T>::type;
} // namespace detail
} // namespace bpstd
#endif /* BPSTD_DETAIL_ENABLE_OVERLOAD_HPP */

View File

@ -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 <type_traits> // std::true_type, std::false_type, etc
#include <functional> // std::reference_wrapper
#include <utility>
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
namespace detail {
template<typename T>
struct is_reference_wrapper : std::false_type {};
template<typename U>
struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
template <typename Base, typename T, typename Derived, typename... Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args)
noexcept(noexcept((::bpstd::forward<Derived>(ref).*pmf)(::bpstd::forward<Args>(args)...)))
-> typename std::enable_if<std::is_function<T>::value &&
std::is_base_of<Base, typename std::decay<Derived>::type>::value,
decltype((::bpstd::forward<Derived>(ref).*pmf)(::bpstd::forward<Args>(args)...))>::type
{
return (bpstd::forward<Derived>(ref).*pmf)(bpstd::forward<Args>(args)...);
}
template <typename Base, typename T, typename RefWrap, typename... Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args)
noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
-> typename std::enable_if<std::is_function<T>::value &&
is_reference_wrapper<typename std::decay<RefWrap>::type>::value,
decltype((ref.get().*pmf)(::bpstd::forward<Args>(args)...))>::type
{
return (ref.get().*pmf)(bpstd::forward<Args>(args)...);
}
template<typename Base, typename T, typename Pointer, typename... Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args)
noexcept(noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
-> typename std::enable_if<std::is_function<T>::value &&
!is_reference_wrapper<typename std::decay<Pointer>::type>::value &&
!std::is_base_of<Base, typename std::decay<Pointer>::type>::value,
decltype(((*::bpstd::forward<Pointer>(ptr)).*pmf)(::bpstd::forward<Args>(args)...))>::type
{
return ((*bpstd::forward<Pointer>(ptr)).*pmf)(bpstd::forward<Args>(args)...);
}
template<typename Base, typename T, typename Derived>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmd, Derived&& ref)
noexcept(noexcept(std::forward<Derived>(ref).*pmd))
-> typename std::enable_if<!std::is_function<T>::value &&
std::is_base_of<Base, typename std::decay<Derived>::type>::value,
decltype(::bpstd::forward<Derived>(ref).*pmd)>::type
{
return bpstd::forward<Derived>(ref).*pmd;
}
template<typename Base, typename T, typename RefWrap>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmd, RefWrap&& ref)
noexcept(noexcept(ref.get().*pmd))
-> typename std::enable_if<!std::is_function<T>::value &&
is_reference_wrapper<typename std::decay<RefWrap>::type>::value,
decltype(ref.get().*pmd)>::type
{
return ref.get().*pmd;
}
template<typename Base, typename T, typename Pointer>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(T Base::*pmd, Pointer&& ptr)
noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd))
-> typename std::enable_if<!std::is_function<T>::value &&
!is_reference_wrapper<typename std::decay<Pointer>::type>::value &&
!std::is_base_of<Base, typename std::decay<Pointer>::type>::value,
decltype((*::bpstd::forward<Pointer>(ptr)).*pmd)>::type
{
return (*bpstd::forward<Pointer>(ptr)).*pmd;
}
template<typename F, typename... Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto INVOKE(F&& f, Args&&... args)
noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
-> typename std::enable_if<!std::is_member_pointer<typename std::decay<F>::type>::value,
decltype(::bpstd::forward<F>(f)(::bpstd::forward<Args>(args)...))>::type
{
return bpstd::forward<F>(f)(bpstd::forward<Args>(args)...);
}
//==========================================================================
// is_nothrow_invocable
//==========================================================================
template <typename Fn, typename...Args>
struct is_nothrow_invocable
{
template <typename Fn2, typename...Args2>
static auto test( Fn2&&, Args2&&... )
-> decltype(INVOKE(std::declval<Fn2>(), std::declval<Args2>()...),
std::integral_constant<bool,noexcept(INVOKE(std::declval<Fn2>(), std::declval<Args2>()...))>{});
static auto test(...)
-> std::false_type;
using type = decltype(test(std::declval<Fn>(), std::declval<Args>()...));
static constexpr bool value = type::value;
};
//==========================================================================
// is_invocable
//==========================================================================
template<typename Fn, typename...Args>
struct is_invocable
{
template <typename Fn2, typename...Args2>
static auto test( Fn2&&, Args2&&... )
-> decltype(INVOKE(std::declval<Fn2>(), std::declval<Args2>()...), std::true_type{});
static auto test(...)
-> std::false_type;
using type = decltype(test(std::declval<Fn>(), std::declval<Args>()...));
static constexpr bool value = type::value;
};
// Used to SFINAE away non-invocable types
template <bool B, typename Fn, typename...Args>
struct invoke_result_impl{};
template <typename Fn, typename...Args>
struct invoke_result_impl<true, Fn, Args...>{
using type = decltype(INVOKE(std::declval<Fn>(), std::declval<Args>()...));
};
template <typename Fn, typename...Args>
struct invoke_result
: invoke_result_impl<is_invocable<Fn,Args...>::value, Fn, Args...>{};
} // namespace detail
} // namespace bpstd
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_INVOKE_HPP */

View File

@ -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 <type_traits>
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 <typename T>
constexpr T&& forward(typename std::remove_reference<T>::type& t) noexcept;
template <typename T>
constexpr T&& forward(typename std::remove_reference<T>::type&& t) noexcept;
/// \}
/// \brief Casts \p x to an rvalue
///
/// \param x the parameter to move
/// \return rvalue reference to \p x
template <typename T>
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 <typename T>
constexpr typename std::remove_reference<T>::type&& move(T&& x) noexcept;
} // namespace bpstd
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
T&& bpstd::forward(typename std::remove_reference<T>::type& t)
noexcept
{
return static_cast<T&&>(t);
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
T&& bpstd::forward(typename std::remove_reference<T>::type&& t)
noexcept
{
return static_cast<T&&>(t);
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
T&& bpstd::move(T& x)
noexcept
{
return static_cast<T&&>(x);
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
typename std::remove_reference<T>::type&& bpstd::move(T&& x)
noexcept
{
return static_cast<T&&>(x);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_MOVE_HPP */

View File

@ -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 <cstddef> // 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 <std::size_t N, typename...Args>
struct nth_type;
template <std::size_t N, typename Arg0, typename...Args>
struct nth_type<N,Arg0,Args...> : nth_type<N-1,Args...>{};
template <typename Arg0, typename...Args>
struct nth_type<0,Arg0,Args...>
{
using type = Arg0;
};
template <std::size_t N, typename...Args>
using nth_type_t = typename nth_type<N,Args...>::type;
} // namespace detail
} // namespace bpstd
#endif /* BPSTD_DETAIL_NTH_TYPE_HPP */

View File

@ -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 <iterator>
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 <typename Iterator, typename U = void>
class proxy_iterator
#if __cplusplus < 201703L
: public std::iterator<
typename std::iterator_traits<Iterator>::iterator_category,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::difference_type,
typename std::iterator_traits<Iterator>::pointer,
typename std::iterator_traits<Iterator>::reference
>
#endif
{
#if __cplusplus < 201703L
using base_type = std::iterator<
typename std::iterator_traits<Iterator>::iterator_category,
typename std::iterator_traits<Iterator>::value_type,
typename std::iterator_traits<Iterator>::difference_type,
typename std::iterator_traits<Iterator>::pointer,
typename std::iterator_traits<Iterator>::reference
>;
#endif
//------------------------------------------------------------------------
// Public Member Types
//------------------------------------------------------------------------
public:
#if __cplusplus >= 201703L
using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
using value_type = typename std::iterator_traits<Iterator>::value_type;
using pointer = typename std::iterator_traits<Iterator>::pointer;
using reference = typename std::iterator_traits<Iterator>::reference;
using difference_type = typename std::iterator_traits<Iterator>::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 <typename UIterator>
constexpr proxy_iterator(const proxy_iterator<UIterator,U>& 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 <typename UIterator>
proxy_iterator& operator=(const proxy_iterator<UIterator,U>& 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 <typename, typename> friend class proxy_iterator;
};
//==========================================================================
// non-member functions : class : proxy_iterator
//==========================================================================
//--------------------------------------------------------------------------
// Random Access
//--------------------------------------------------------------------------
template<typename Iterator, typename U>
BPSTD_CPP14_CONSTEXPR proxy_iterator<Iterator,U>
operator+(const proxy_iterator<Iterator,U>& lhs,
typename proxy_iterator<Iterator,U>::difference_type rhs) noexcept;
template<typename Iterator, typename U>
BPSTD_CPP14_CONSTEXPR proxy_iterator<Iterator,U>
operator+(typename proxy_iterator<Iterator,U>::difference_type lhs,
const proxy_iterator<Iterator,U>& rhs) noexcept;
template<typename Iterator, typename U>
BPSTD_CPP14_CONSTEXPR proxy_iterator<Iterator,U>
operator-(const proxy_iterator<Iterator,U>& lhs,
typename proxy_iterator<Iterator,U>::difference_type rhs) noexcept;
} // namespace detail
} // namespace bpstd
//==============================================================================
// definitions : class : proxy_iterator
//==============================================================================
//------------------------------------------------------------------------------
// Constructors / Assignment
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline constexpr bpstd::detail::proxy_iterator<Iterator,U>::
proxy_iterator(const Iterator& it)
noexcept
: m_iter{it}
{
}
template<typename Iterator, typename U>
template <typename UIterator>
inline constexpr bpstd::detail::proxy_iterator<Iterator,U>
::proxy_iterator(const proxy_iterator<UIterator,U>& it)
noexcept
: m_iter{it.m_iter}
{
}
template<typename Iterator, typename U>
template <typename UIterator>
inline bpstd::detail::proxy_iterator<Iterator,U>&
bpstd::detail::proxy_iterator<Iterator,U>::operator=(const proxy_iterator<UIterator,U>& it)
noexcept
{
m_iter = it.m_iter;
return (*this);
}
//------------------------------------------------------------------------------
// Iteration
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>&
bpstd::detail::proxy_iterator<Iterator,U>::operator++()
noexcept
{
++m_iter;
return (*this);
}
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>
bpstd::detail::proxy_iterator<Iterator,U>::operator++(int)
noexcept
{
return proxy_iterator{m_iter++};
}
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>&
bpstd::detail::proxy_iterator<Iterator,U>::operator--()
noexcept
{
--m_iter;
return (*this);
}
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>
bpstd::detail::proxy_iterator<Iterator,U>::operator--(int)
noexcept
{
return proxy_iterator{m_iter--};
}
//------------------------------------------------------------------------------
// Random Access
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>&
bpstd::detail::proxy_iterator<Iterator,U>::operator+=(difference_type n)
noexcept
{
m_iter += n;
return (*this);
}
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>&
bpstd::detail::proxy_iterator<Iterator,U>::operator-=(difference_type n)
noexcept
{
m_iter -= n;
return (*this);
}
template<typename Iterator, typename U>
inline constexpr typename bpstd::detail::proxy_iterator<Iterator,U>::difference_type
bpstd::detail::proxy_iterator<Iterator,U>::operator-(const proxy_iterator<Iterator,U>& rhs)
const noexcept
{
return m_iter - rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr typename bpstd::detail::proxy_iterator<Iterator,U>::reference
bpstd::detail::proxy_iterator<Iterator,U>::operator[](difference_type index)
const noexcept
{
return m_iter[index];
}
//------------------------------------------------------------------------------
// Observers
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline constexpr typename bpstd::detail::proxy_iterator<Iterator,U>::pointer
bpstd::detail::proxy_iterator<Iterator,U>::operator->()
const noexcept
{
return m_iter;
}
template<typename Iterator, typename U>
inline constexpr typename bpstd::detail::proxy_iterator<Iterator,U>::reference
bpstd::detail::proxy_iterator<Iterator,U>::operator*()
const noexcept
{
return *m_iter;
}
//------------------------------------------------------------------------------
// Comparisons
//------------------------------------------------------------------------------
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::operator==(const proxy_iterator& rhs)
const noexcept
{
return m_iter == rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::operator!=(const proxy_iterator& rhs)
const noexcept
{
return m_iter != rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::operator<(const proxy_iterator& rhs)
const noexcept
{
return m_iter < rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::operator<=(const proxy_iterator& rhs)
const noexcept
{
return m_iter <= rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::operator>(const proxy_iterator& rhs)
const noexcept
{
return m_iter > rhs.m_iter;
}
template<typename Iterator, typename U>
inline constexpr bool
bpstd::detail::proxy_iterator<Iterator,U>::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<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>
bpstd::detail::operator+(const proxy_iterator<Iterator,U>& lhs,
typename proxy_iterator<Iterator,U>::difference_type rhs)
noexcept
{
return proxy_iterator<Iterator,U>{lhs} += rhs;
}
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>
bpstd::detail::operator+(typename proxy_iterator<Iterator,U>::difference_type lhs,
const proxy_iterator<Iterator,U>& rhs)
noexcept
{
return proxy_iterator<Iterator,U>{rhs} += lhs;
}
template<typename Iterator, typename U>
inline BPSTD_CPP14_CONSTEXPR bpstd::detail::proxy_iterator<Iterator,U>
bpstd::detail::operator-(const proxy_iterator<Iterator,U>& lhs,
typename proxy_iterator<Iterator,U>::difference_type rhs)
noexcept
{
return proxy_iterator<Iterator,U>{lhs} -= rhs;
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_PROXY_ITERATOR_HPP */

View File

@ -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 <cstddef> // std::size_t
#include <utility> // std::forward
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
namespace detail {
//==========================================================================
// class : variant_base
//==========================================================================
////////////////////////////////////////////////////////////////////////////
/// \brief The base class used by variant
////////////////////////////////////////////////////////////////////////////
template <bool IsTrivial, typename...Types>
class variant_base;
//==========================================================================
// class : variant_base<true, Types...>
//==========================================================================
template <typename...Types>
class variant_base<true,Types...>
{
//------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------
public:
constexpr variant_base();
template <std::size_t N, typename...Args>
constexpr variant_base(variant_index_tag<N>, Args&&...args);
//------------------------------------------------------------------------
// Protected Members
//------------------------------------------------------------------------
protected:
variant_union<true,Types...> m_union;
std::size_t m_index;
//---------------------------------------------------------------------
// Protected Member Functions
//---------------------------------------------------------------------
protected:
void destroy_active_object();
};
//==========================================================================
// class : variant_base<false, Types...>
//==========================================================================
template <typename...Types>
class variant_base<false,Types...>
{
public:
constexpr variant_base();
template <std::size_t N, typename...Args>
constexpr variant_base(variant_index_tag<N>, Args&&...args);
~variant_base();
//---------------------------------------------------------------------
// Protected Members
//---------------------------------------------------------------------
protected:
variant_union<false,Types...> m_union;
std::size_t m_index;
//---------------------------------------------------------------------
// Protected Member Functions
//---------------------------------------------------------------------
protected:
void destroy_active_object();
//---------------------------------------------------------------------
// Private Static Member Functions
//---------------------------------------------------------------------
private:
struct destroy_visitor
{
template <typename T>
inline BPSTD_INLINE_VISIBILITY
void operator()(T& v) {
v.~T();
}
};
};
} // namespace detail
} // namespace bpstd
//==============================================================================
// class : variant_base<true, Types...>
//==============================================================================
//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------
template <typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_base<true,Types...>::variant_base()
: m_union{},
m_index{static_cast<std::size_t>(-1)}
{
}
template <typename...Types>
template <std::size_t N, typename...Args>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_base<true,Types...>::variant_base(variant_index_tag<N>,
Args&&...args)
: m_union{variant_index_tag<N>{}, std::forward<Args>(args)...},
m_index{N}
{
}
//------------------------------------------------------------------------------
// Protected Members
//------------------------------------------------------------------------------
template <typename...Types>
inline BPSTD_INLINE_VISIBILITY
void bpstd::detail::variant_base<true,Types...>::destroy_active_object()
{
m_index = static_cast<std::size_t>(-1);
}
//==============================================================================
// class : variant_base<false, Types...>
//==============================================================================
//------------------------------------------------------------------------------
// Constructors / Destructor
//------------------------------------------------------------------------------
template <typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_base<false,Types...>::variant_base()
: m_union{},
m_index{static_cast<std::size_t>(-1)}
{
}
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable:4702)
#endif
template <typename...Types>
template <std::size_t N, typename...Args>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_base<false,Types...>::variant_base(variant_index_tag<N>,
Args&&...args)
: m_union{variant_index_tag<N>{}, std::forward<Args>(args)...},
m_index{N}
{
}
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
//------------------------------------------------------------------------------
template <typename...Types>
inline BPSTD_INLINE_VISIBILITY
bpstd::detail::variant_base<false,Types...>::~variant_base()
{
destroy_active_object();
}
//------------------------------------------------------------------------------
// Protected Members
//------------------------------------------------------------------------------
template <typename...Types>
inline BPSTD_INLINE_VISIBILITY
void bpstd::detail::variant_base<false,Types...>::destroy_active_object()
{
if (m_index == static_cast<std::size_t>(-1)) {
return;
}
visit_union(m_index, destroy_visitor{}, m_union);
m_index = static_cast<std::size_t>(-1);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_VARIANT_BASE_HPP */

View File

@ -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 <bool IsTrivial, typename...Types>
union variant_union;
template <bool IsTrivial, typename...Types>
class variant_base;
} // namespace detail
template <typename...Types>
class variant;
} // namespace bpstd
#endif /* BPSTD_DETAIL_VARIANT_FWDS_HPP */

View File

@ -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 <typename Variant>
struct variant_first_type;
template <bool IsTrivial, typename Type0, typename...Types>
struct variant_first_type<variant_union<IsTrivial, Type0, Types...>>
{
using type = Type0;
};
template <bool IsTrivial, typename Type0, typename...Types>
struct variant_first_type<variant_base<IsTrivial, Type0, Types...>>
{
using type = Type0;
};
template <typename Type0, typename...Types>
struct variant_first_type<variant<Type0, Types...>>
{
using type = Type0;
};
template <typename Variant>
struct variant_first_type<Variant&>
{
using type = typename variant_first_type<Variant>::type&;
};
template <typename Variant>
struct variant_first_type<Variant&&>
{
using type = typename variant_first_type<Variant>::type&&;
};
template <typename Variant>
struct variant_first_type<const Variant>
{
using type = const typename variant_first_type<Variant>::type;
};
template <typename Variant>
struct variant_first_type<const Variant&>
{
using type = const typename variant_first_type<Variant>::type&;
};
template <typename Variant>
struct variant_first_type<const Variant&&>
{
using type = const typename variant_first_type<Variant>::type&&;
};
template <typename Variant>
using variant_first_type_t = typename variant_first_type<Variant>::type;
//--------------------------------------------------------------------------
template <typename Visitor, typename...Variants>
struct variant_visitor_invoke_result
: invoke_result<Visitor,variant_first_type_t<Variants>...>{};
template <typename Visitor, typename...Variants>
using variant_visitor_invoke_result_t
= typename variant_visitor_invoke_result<Visitor, Variants...>::type;
} // namespace detail
} // namespace bpstd
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_VARIANT_TRAITS_HPP */

View File

@ -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 <cstddef> // std::size_t
#include <type_traits> // std::decay
#include <initializer_list>
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
namespace detail {
template <typename From, typename To>
struct match_cv {
using type = To;
};
template <typename From, typename To>
struct match_cv<const From, To> {
using type = const To;
};
template <typename From, typename To>
struct match_cv<volatile From, To> {
using type = volatile To;
};
template <typename From, typename To>
struct match_cv<const volatile From, To> {
using type = const volatile To;
};
template <typename From, typename To>
struct match_reference {
using type = To&&;
};
template <typename From, typename To>
struct match_reference<From&&, To> {
using type = To&&;
};
template <typename From, typename To>
struct match_reference<From&,To> {
using type = To&;
};
template <typename From, typename To>
using match_cvref = match_reference<From,
typename match_cv<
typename std::remove_reference<From>::type,To
>::type
>;
template <typename From, typename To>
using match_cvref_t = typename match_cvref<From,To>::type;
////////////////////////////////////////////////////////////////////////////
/// \brief A tag type used to represent an empty variant
////////////////////////////////////////////////////////////////////////////
struct variant_empty{};
template <std::size_t N>
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 <bool IsTrivial, typename...Types>
union variant_union;
/// \brief A type-trait for retrieving the number of elements in a variant
/// union
template <typename T>
struct variant_union_size
: variant_union_size<typename std::decay<T>::type>{};
template <bool B, typename...Types>
struct variant_union_size<variant_union<B,Types...>>
: std::integral_constant<std::size_t,sizeof...(Types)>{};
//==========================================================================
// union : variant_union<true,Type0,Types...>
//==========================================================================
// Partial specialization: All types are trivial; is trivially destructible
template <typename Type0, typename...Types>
union variant_union<true,Type0,Types...>
{
//------------------------------------------------------------------------
// Public Members Types
//------------------------------------------------------------------------
using current_type = Type0;
using next_type = variant_union<true,Types...>;
//------------------------------------------------------------------------
// Public Members
//------------------------------------------------------------------------
variant_empty empty;
current_type current;
next_type next;
//------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------
constexpr variant_union();
template <typename...Args>
constexpr variant_union(variant_index_tag<0>, Args&&...args);
template <std::size_t N, typename...Args>
constexpr variant_union(variant_index_tag<N>, Args&&...args);
};
//==========================================================================
// union : variant_union<false,Type0,Types...>
//==========================================================================
// 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 <typename Type0, typename...Types>
union variant_union<false,Type0,Types...>
{
//------------------------------------------------------------------------
// Public Members Types
//------------------------------------------------------------------------
using current_type = Type0;
using next_type = variant_union<false,Types...>;
//------------------------------------------------------------------------
// Public Members
//------------------------------------------------------------------------
variant_empty empty;
current_type current;
next_type next;
//------------------------------------------------------------------------
// Constructors / Destructor
//------------------------------------------------------------------------
constexpr variant_union();
template <typename...Args>
constexpr variant_union(variant_index_tag<0>, Args&&...args);
template <std::size_t N, typename...Args>
constexpr variant_union(variant_index_tag<N>, Args&&...args);
~variant_union(){}
};
//==========================================================================
// union : variant_union<B>
//==========================================================================
template <bool B>
union variant_union<B>
{
//------------------------------------------------------------------------
// Public Members
//------------------------------------------------------------------------
variant_empty empty;
//------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------
constexpr variant_union();
template <typename...Args>
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 <typename Fn, typename VariantUnion>
BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t<Fn, VariantUnion>
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 <typename Fn, typename VariantUnion, typename UVariantUnion>
BPSTD_CPP14_CONSTEXPR bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion,UVariantUnion>
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 <std::size_t N, bool IsTrivial, typename...Types>
constexpr bpstd::detail::nth_type_t<N,Types...>&
union_get(variant_union<IsTrivial,Types...>& u);
template <std::size_t N, bool IsTrivial, typename...Types>
constexpr const bpstd::detail::nth_type_t<N,Types...>&
union_get(const variant_union<IsTrivial,Types...>& u);
template <std::size_t N, bool IsTrivial, typename...Types>
constexpr bpstd::detail::nth_type_t<N,Types...>&&
union_get(variant_union<IsTrivial,Types...>&& u);
template <std::size_t N, bool IsTrivial, typename...Types>
constexpr const bpstd::detail::nth_type_t<N,Types...>&&
union_get(const variant_union<IsTrivial,Types...>&& u);
/// \}
} // namespace detail
} // namespace bpstd
//==============================================================================
// union : variant_union<true, Type0, Types...>
//==============================================================================
//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------
template <typename Type0, typename...Types>
inline constexpr bpstd::detail::variant_union<true, Type0, Types...>
::variant_union()
: empty{}
{
}
template <typename Type0, typename...Types>
template <typename...Args>
inline constexpr bpstd::detail::variant_union<true, Type0, Types...>
::variant_union(variant_index_tag<0>, Args&&...args)
: current(bpstd::forward<Args>(args)...)
{
}
template <typename Type0, typename...Types>
template <std::size_t N, typename...Args>
inline constexpr bpstd::detail::variant_union<true, Type0, Types...>
::variant_union(variant_index_tag<N>, Args&&...args)
: next{variant_index_tag<N-1>{}, bpstd::forward<Args>(args)...}
{
}
//==============================================================================
// union : variant_union<false, Type0, Types...>
//==============================================================================
//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------
template <typename Type0, typename...Types>
inline constexpr bpstd::detail::variant_union<false, Type0, Types...>
::variant_union()
: empty{}
{
}
template <typename Type0, typename...Types>
template <typename...Args>
inline constexpr bpstd::detail::variant_union<false, Type0, Types...>
::variant_union(variant_index_tag<0>, Args&&...args)
: current(bpstd::forward<Args>(args)...)
{
}
template <typename Type0, typename...Types>
template <std::size_t N, typename...Args>
inline constexpr bpstd::detail::variant_union<false, Type0, Types...>
::variant_union(variant_index_tag<N>, Args&&...args)
: next{variant_index_tag<N-1>{}, bpstd::forward<Args>(args)...}
{
}
//==============================================================================
// union : variant_union<B>
//==============================================================================
//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------
template <bool B>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_union<B>::variant_union()
: empty{}
{
// base-case; should never be executed
}
template <bool B>
template <typename...Args>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::variant_union<B>::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 <typename Fn, typename VariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion>
do_visit_union(variant_index_tag<1>,
std::size_t n,
Fn&& fn,
VariantUnion&& v)
{
BPSTD_UNUSED(n);
return bpstd::forward<Fn>(fn)(
union_get<0>(bpstd::forward<VariantUnion>(v))
);
}
template <std::size_t N, typename Fn, typename VariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion>
do_visit_union(variant_index_tag<N>,
std::size_t n,
Fn&& fn,
VariantUnion&& v)
{
using size_type = variant_union_size<VariantUnion>;
if (n == 0) {
return bpstd::forward<Fn>(fn)(
union_get<0>(bpstd::forward<VariantUnion>(v))
);
}
return do_visit_union(
variant_index_tag<(size_type::value - 1)>{},
n-1,
bpstd::forward<Fn>(fn),
static_cast<match_cvref_t<VariantUnion,decltype(v.next)>>(v.next)
);
}
// Double-case
template <typename Fn, typename VariantUnion, typename UVariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion,UVariantUnion>
do_visit_union(variant_index_tag<1>,
std::size_t n,
Fn&& fn,
VariantUnion&& v0,
UVariantUnion&& v1)
{
BPSTD_UNUSED(n);
return bpstd::forward<Fn>(fn)(
union_get<0>(bpstd::forward<VariantUnion>(v0)),
union_get<0>(bpstd::forward<UVariantUnion>(v1))
);
}
template <std::size_t N, typename Fn, typename VariantUnion, typename UVariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion,UVariantUnion>
do_visit_union(variant_index_tag<N>,
std::size_t n,
Fn&& fn,
VariantUnion&& v0,
UVariantUnion&& v1)
{
using size_type = variant_union_size<VariantUnion>;
if (n == 0) {
return bpstd::forward<Fn>(fn)(
union_get<0>(bpstd::forward<VariantUnion>(v0)),
union_get<0>(bpstd::forward<UVariantUnion>(v1))
);
}
return do_visit_union(
variant_index_tag<(size_type::value - 1)>{},
n-1,
bpstd::forward<Fn>(fn),
static_cast<match_cvref_t<VariantUnion,decltype(v0.next)>>(v0.next),
static_cast<match_cvref_t<UVariantUnion,decltype(v1.next)>>(v1.next)
);
}
}} // namespace bpstd::detail
template <typename Fn, typename VariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn,VariantUnion>
bpstd::detail::visit_union(std::size_t n, Fn&& fn, VariantUnion&& v)
{
using size_type = variant_union_size<VariantUnion>;
return detail::do_visit_union(
variant_index_tag<size_type::value>{},
n,
bpstd::forward<Fn>(fn),
bpstd::forward<VariantUnion>(v)
);
}
template <typename Fn, typename VariantUnion, typename UVariantUnion>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
bpstd::detail::variant_visitor_invoke_result_t<Fn, VariantUnion, UVariantUnion>
bpstd::detail::visit_union(std::size_t n,
Fn&& fn,
VariantUnion&& v1,
UVariantUnion&& v2)
{
using size_type = variant_union_size<VariantUnion>;
return detail::do_visit_union(
variant_index_tag<size_type::value>{},
n,
bpstd::forward<Fn>(fn),
bpstd::forward<VariantUnion>(v1),
bpstd::forward<UVariantUnion>(v2)
);
}
//------------------------------------------------------------------------------
namespace bpstd { namespace detail {
// private implementation: recurse on index
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
nth_type_t<N,Types...>&
do_union_get(variant_index_tag<N>, variant_union<IsTrivial,Types...>& u)
{
return do_union_get(variant_index_tag<N-1>{}, u.next);
}
template <bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
nth_type_t<0,Types...>&
do_union_get(variant_index_tag<0>, variant_union<IsTrivial,Types...>& u)
{
return u.current;
}
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
const nth_type_t<N,Types...>&
do_union_get(variant_index_tag<N>, const variant_union<IsTrivial,Types...>& u)
{
return do_union_get(variant_index_tag<N-1>{}, u.next);
}
template <bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
const nth_type_t<0,Types...>&
do_union_get(variant_index_tag<0>, const variant_union<IsTrivial,Types...>& u)
{
return u.current;
}
}} // namespace bpstd::detail
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::nth_type_t<N,Types...>&
bpstd::detail::union_get(variant_union<IsTrivial,Types...>& u)
{
static_assert(N < sizeof...(Types), "N index out of bounds");
return do_union_get(variant_index_tag<N>{}, u);
}
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
const bpstd::detail::nth_type_t<N,Types...>&
bpstd::detail::union_get(const variant_union<IsTrivial,Types...>& u)
{
static_assert(N < sizeof...(Types), "N index out of bounds");
return do_union_get(variant_index_tag<N>{}, u);
}
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::nth_type_t<N,Types...>&&
bpstd::detail::union_get(variant_union<IsTrivial,Types...>&& u)
{
static_assert(N < sizeof...(Types), "N index out of bounds");
return bpstd::move(do_union_get(variant_index_tag<N>{}, u));
}
template <std::size_t N, bool IsTrivial, typename...Types>
inline BPSTD_INLINE_VISIBILITY constexpr
const bpstd::detail::nth_type_t<N,Types...>&&
bpstd::detail::union_get(const variant_union<IsTrivial,Types...>&& u)
{
static_assert(N < sizeof...(Types), "N index out of bounds");
return bpstd::move(do_union_get(variant_index_tag<N>{}, u));
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_VARIANT_UNION_HPP */

View File

@ -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 <new> // placement new
#include <utility> // 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 <typename T>
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 <typename T>
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 <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY
void operator()(T& self, U&& other) const
{
new (&self) T(bpstd::forward<U>(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 <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY
void operator()(T& self, U&& other) const
{
self = bpstd::forward<U>(other);
}
};
////////////////////////////////////////////////////////////////////////////
/// \brief A visitor for swapping the underlying elements of a variant
////////////////////////////////////////////////////////////////////////////
struct variant_swap_visitor
{
template <typename T>
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 <typename T, typename Arg>
struct variant_assign_visitor
{
Arg m_value;
template <typename UArg>
inline BPSTD_INLINE_VISIBILITY
variant_assign_visitor(UArg&& u)
: m_value(bpstd::forward<UArg>(u))
{
}
template <typename U>
inline BPSTD_INLINE_VISIBILITY
void operator()(U&)
{
}
inline BPSTD_INLINE_VISIBILITY
void operator()(T& x)
{
x = static_cast<Arg>(m_value);
}
};
////////////////////////////////////////////////////////////////////////////
/// \brief A visitor for emplacing elements into a variant
////////////////////////////////////////////////////////////////////////////
template <typename T, typename Tuple>
struct variant_emplace_visitor
{
Tuple m_tuple;
template <typename UTuple>
inline BPSTD_INLINE_VISIBILITY
variant_emplace_visitor(UTuple&& tuple)
: m_tuple{bpstd::forward<UTuple>(tuple)}
{
}
template <typename U>
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<tuple_size<Tuple>::value>{}
);
}
template <typename UTuple, std::size_t... I>
inline BPSTD_INLINE_VISIBILITY
static void emplace_from_tuple(void* p, UTuple&& tuple, index_sequence<I...>)
{
new(p) T(std::get<I>(bpstd::forward<UTuple>(tuple))...);
}
};
} // namespace detail
} // namespace bpstd
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_DETAIL_VARIANT_VISITORS_HPP */

View File

@ -0,0 +1,199 @@
////////////////////////////////////////////////////////////////////////////////
/// \file exception.hpp
///
/// \brief This header provides definitions from the C++ header <exception>
////////////////////////////////////////////////////////////////////////////////
/*
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 <exception>
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(<cxxabi.h>)
# 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 <cxxabi.h>
# include <cstring>
# 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 <cstring>
# 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<const byte*>(::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<const byte*>(::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<int>(std::uncaught_exception());
#endif
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_EXCEPTION_HPP */

View File

@ -0,0 +1,699 @@
////////////////////////////////////////////////////////////////////////////////
/// \file functional.hpp
///
/// \brief This header provides definitions from the C++ header <functional>
////////////////////////////////////////////////////////////////////////////////
/*
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 <functional> // 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>(f), std::forward<Args>(args)...)
///
/// \param function Callable object to be invoked
/// \param args arguments to pass to \p function
template <typename Func, typename... Args>
constexpr invoke_result_t<Func,Args...> invoke(Func&& function, Args&&... args)
noexcept(is_nothrow_invocable<Func,Args...>::value);
namespace detail {
template <typename Fn>
struct not_fn_t
{
Fn fn;
template <typename...Args>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
auto operator()(Args&&... args) &
noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...)))
-> decltype(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...))
{
return !::bpstd::invoke(fn, bpstd::forward<Args>(args)...);
}
template <typename...Args>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
auto operator()(Args&&... args) &&
noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...)))
-> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...))
{
return !::bpstd::invoke(std::move(fn), bpstd::forward<Args>(args)...);
}
template <typename...Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(Args&&... args) const&
noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...)))
-> decltype(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...))
{
return !::bpstd::invoke(fn, bpstd::forward<Args>(args)...);
}
template <typename...Args>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(Args&&... args) const&&
noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...)))
-> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...))
{
return !::bpstd::invoke(std::move(fn), bpstd::forward<Args>(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 <typename Fn>
constexpr detail::not_fn_t<decay_t<Fn>> not_fn(Fn&& fn);
//============================================================================
// struct : plus
//============================================================================
template <typename T = void>
struct plus
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs + rhs;
}
};
template <>
struct plus<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) + ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) + bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : minus
//============================================================================
template <typename T = void>
struct minus
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs - rhs;
}
};
template <>
struct minus<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) - ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) - bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : multiplies
//============================================================================
template <typename T = void>
struct multiplies
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs * rhs;
}
};
template <>
struct multiplies<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) * ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) * bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : divides
//============================================================================
template <typename T = void>
struct divides
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs / rhs;
}
};
template <>
struct divides<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) / ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) / bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : modulus
//============================================================================
template <typename T = void>
struct modulus
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs % rhs;
}
};
template <>
struct modulus<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) % ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) % bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : negate
//============================================================================
template <typename T = void>
struct negate
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& arg)
const
{
return -arg;
}
};
template <>
struct negate<void>
{
using is_transparent = true_type;
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& arg) const
-> decltype(-::bpstd::forward<T>(arg))
{
return -bpstd::forward<T>(arg);
}
};
//============================================================================
// struct : equal_to
//============================================================================
template <typename T = void>
struct equal_to
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs == rhs;
}
};
template <>
struct equal_to<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) == ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) == bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : not_equal_to
//============================================================================
template <typename T = void>
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<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) != ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) != bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : greater
//============================================================================
template <typename T = void>
struct greater
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs > rhs;
}
};
template <>
struct greater<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) > ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) > bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : greater_equal
//============================================================================
template <typename T = void>
struct greater_equal
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs >= rhs;
}
};
template <>
struct greater_equal<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) >= ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) >= bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : less
//============================================================================
template <typename T = void>
struct less
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs < rhs;
}
};
template <>
struct less<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) < ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) < bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : less_equal
//============================================================================
template <typename T = void>
struct less_equal
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs <= rhs;
}
};
template <>
struct less_equal<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) <= ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) <= bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : logical_and
//============================================================================
template <typename T = void>
struct logical_and
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs && rhs;
}
};
template <>
struct logical_and<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) && ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) && bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : logical_or
//============================================================================
template <typename T = void>
struct logical_or
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& lhs, const T& rhs)
const
{
return lhs || rhs;
}
};
template <>
struct logical_or<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) || ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) || bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : logical_not
//============================================================================
template <typename T = void>
struct logical_not
{
inline BPSTD_INLINE_VISIBILITY constexpr
bool operator()(const T& arg)
const
{
return !arg;
}
};
template <>
struct logical_not<void>
{
using is_transparent = true_type;
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& arg) const
-> decltype(!::bpstd::forward<T>(arg))
{
return !bpstd::forward<T>(arg);
}
};
//============================================================================
// struct : bit_and
//============================================================================
template <typename T = void>
struct bit_and
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs & rhs;
}
};
template <>
struct bit_and<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) & ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) & bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : bit_or
//============================================================================
template <typename T = void>
struct bit_or
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs | rhs;
}
};
template <>
struct bit_or<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) | ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) | bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : bit_xor
//============================================================================
template <typename T = void>
struct bit_xor
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& lhs, const T& rhs)
const
{
return lhs ^ rhs;
}
};
template <>
struct bit_xor<void>
{
using is_transparent = true_type;
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& lhs, U&& rhs) const
-> decltype(::bpstd::forward<T>(lhs) ^ ::bpstd::forward<U>(rhs))
{
return bpstd::forward<T>(lhs) ^ bpstd::forward<U>(rhs);
}
};
//============================================================================
// struct : bit_not
//============================================================================
template <typename T = void>
struct bit_not
{
inline BPSTD_INLINE_VISIBILITY constexpr
T operator()(const T& arg)
const
{
return ~arg;
}
};
template <>
struct bit_not<void>
{
using is_transparent = true_type;
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
auto operator()(T&& arg) const
-> decltype(~::bpstd::forward<T>(arg))
{
return ~bpstd::forward<T>(arg);
}
};
} // namespace bpstd
//==============================================================================
// definition : invoke
//==============================================================================
template <typename Func, typename... Args>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::invoke_result_t<Func,Args...> bpstd::invoke(Func&& function, Args&&... args)
noexcept(is_nothrow_invocable<Func,Args...>::value)
{
return detail::INVOKE(bpstd::forward<Func>(function), bpstd::forward<Args>(args)...);
}
//==============================================================================
// definition : not_fn
//==============================================================================
template <typename Fn>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::not_fn_t<bpstd::decay_t<Fn>> bpstd::not_fn(Fn&& fn)
{
static_assert(
is_move_constructible<Fn>::value,
"Fn must be move constructible"
);
static_assert(
is_constructible<decay_t<Fn>,Fn>::value,
"Fn must be constructible from an instance of fn"
);
return { bpstd::forward<Fn>(fn) };
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_FUNCTIONAL_HPP */

View File

@ -0,0 +1,278 @@
////////////////////////////////////////////////////////////////////////////////
/// \file iterator.hpp
///
/// \brief This header provides definitions from the C++ header <iterator>
////////////////////////////////////////////////////////////////////////////////
/*
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 <iterator>
#include <cstddef> // std::size_t
#include <initializer_list>
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
//============================================================================
// class : reverse_iterator
//============================================================================
template <typename T>
using reverse_iterator = std::reverse_iterator<T>;
//============================================================================
// 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 <typename Iterator>
constexpr reverse_iterator<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 <typename C>
constexpr auto data(C& c) -> decltype(c.data());
template <typename C>
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 <typename T, std::size_t N>
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 <typename E>
constexpr const E* data(std::initializer_list<E> il) noexcept;
//----------------------------------------------------------------------------
/// \brief Queries whether \p c is empty
///
/// \param c the container to query
/// \return true if \p is empty
template <typename C>
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 <typename T, std::size_t N>
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 <typename E>
constexpr bool empty(std::initializer_list<E> il) noexcept;
//----------------------------------------------------------------------------
/// \brief Gets the size of a container
///
/// \param c the container to check
/// \return the container's size
template <typename C>
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 <typename T, std::size_t N>
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 <typename C>
constexpr auto ssize(const C& c)
-> common_type_t<std::ptrdiff_t, make_signed_t<decltype(c.size())>>;
/// \brief Gets the signed size of an array
///
/// \param array the array to get the size from
/// \return the size of an array
template <typename T, std::ptrdiff_t N>
constexpr std::ptrdiff_t ssize(const T (&array)[N]) noexcept;
} // namespace bpstd
//==============================================================================
// non-member functions : class : reverse_iterator
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename Iterator>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::reverse_iterator<Iterator>
bpstd::make_reverse_iterator(Iterator i)
{
return reverse_iterator<Iterator>{i};
}
//==============================================================================
// non-member functions
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename C>
inline BPSTD_INLINE_VISIBILITY constexpr
auto bpstd::data(C& c)
-> decltype(c.data())
{
return c.data();
}
template <typename C>
inline BPSTD_INLINE_VISIBILITY constexpr
auto bpstd::data(const C& c)
-> decltype(c.data())
{
return c.data();
}
template <typename T, std::size_t N>
inline BPSTD_INLINE_VISIBILITY constexpr
T* bpstd::data(T (&array)[N])
noexcept
{
return array;
}
template <typename E>
inline BPSTD_INLINE_VISIBILITY constexpr
const E* bpstd::data(std::initializer_list<E> il)
noexcept
{
return il.begin();
}
//------------------------------------------------------------------------------
template <typename C>
inline BPSTD_INLINE_VISIBILITY constexpr
auto bpstd::empty(const C& c)
-> decltype(c.empty())
{
return c.empty();
}
template <typename T, std::size_t N>
inline BPSTD_INLINE_VISIBILITY constexpr
bool bpstd::empty(const T (&)[N])
noexcept
{
return N == 0;
}
template <typename E>
inline BPSTD_INLINE_VISIBILITY constexpr
bool bpstd::empty(std::initializer_list<E> il)
noexcept
{
return il.begin() == il.end();
}
//------------------------------------------------------------------------------
template <typename C>
inline BPSTD_INLINE_VISIBILITY constexpr
auto bpstd::size(const C& c)
-> decltype(c.size())
{
return c.size();
}
template <typename T, std::size_t N>
inline BPSTD_INLINE_VISIBILITY constexpr
std::size_t bpstd::size(const T (&)[N])
noexcept
{
return N;
}
//------------------------------------------------------------------------------
template <typename C>
inline BPSTD_INLINE_VISIBILITY constexpr
auto bpstd::ssize(const C& c)
-> bpstd::common_type_t<std::ptrdiff_t, bpstd::make_signed_t<decltype(c.size())>>
{
using type = bpstd::common_type_t<std::ptrdiff_t, bpstd::make_signed_t<decltype(c.size())>>;
return static_cast<type>(c.size());
}
template <typename T, std::ptrdiff_t N>
inline BPSTD_INLINE_VISIBILITY constexpr
std::ptrdiff_t bpstd::ssize(const T (&)[N])
noexcept
{
return N;
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_ITERATOR_HPP */

View File

@ -0,0 +1,261 @@
////////////////////////////////////////////////////////////////////////////////
/// \file memory.hpp
///
/// \brief This header provides definitions from the C++ header <memory>
////////////////////////////////////////////////////////////////////////////////
/*
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 <memory> // std::unique_ptr
#include <cstddef> // std::size_t
#include <type_traits> // std::declval
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
namespace detail {
template <typename T>
struct make_unique_result
{
using object = T;
};
template <typename T>
struct make_unique_result<T[]>
{
using unbounded_array = T[];
};
template <typename T, std::size_t N>
struct make_unique_result<T[N]>
{
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 <typename T, typename...Args>
std::unique_ptr<typename detail::make_unique_result<T>::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 <typename T>
std::unique_ptr<typename detail::make_unique_result<T>::unbounded_array>
make_unique(std::size_t size);
// Construction of arrays of known bound is disallowed
template <typename T>
std::unique_ptr<typename detail::make_unique_result<T>::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 <typename T>
std::unique_ptr<typename detail::make_unique_result<T>::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 <typename T>
std::unique_ptr<typename detail::make_unique_result<T>::unbounded_array>
make_unique_for_overwrite(std::size_t size);
// Construction of arrays of known bound is disallowed
template <typename T>
std::unique_ptr<typename detail::make_unique_result<T>::bounded_array>
make_unique_for_overwrite() = delete;
//----------------------------------------------------------------------------
namespace detail {
template <typename T, typename = void>
struct has_to_address : false_type{};
template <typename T>
struct has_to_address<T,void_t<decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))>>
: true_type{};
//--------------------------------------------------------------------------
template <bool, typename T>
struct operator_deref
{
using type = decltype(std::declval<const T&>().operator->());
};
template <typename T>
struct operator_deref<true, T>{};
//--------------------------------------------------------------------------
template <typename T, typename = void>
struct to_address_result
: operator_deref<std::is_pointer<remove_cvref_t<T>>::value, T>{};
template <typename T>
struct to_address_result<T,void_t<decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))>>
{
using type = decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()));
};
template <typename T>
using to_address_result_t = typename to_address_result<T>::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 <typename T>
constexpr T* to_address(T* p) noexcept;
template <typename T>
constexpr detail::to_address_result_t<T> to_address(const T& p) noexcept;
/// \}
} // namespace bpstd
template <typename T, typename...Args>
inline BPSTD_INLINE_VISIBILITY
std::unique_ptr<typename bpstd::detail::make_unique_result<T>::object>
bpstd::make_unique(Args&&...args)
{
return std::unique_ptr<T>{new T(bpstd::forward<Args>(args)...)};
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY
std::unique_ptr<typename bpstd::detail::make_unique_result<T>::unbounded_array>
bpstd::make_unique(std::size_t size)
{
return std::unique_ptr<T>{new remove_extent_t<T>[size]()};
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY
std::unique_ptr<typename bpstd::detail::make_unique_result<T>::object>
bpstd::make_unique_for_overwrite()
{
return std::unique_ptr<T>{new T};
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY
std::unique_ptr<typename bpstd::detail::make_unique_result<T>::unbounded_array>
bpstd::make_unique_for_overwrite(std::size_t size)
{
return std::unique_ptr<T>{new remove_extent_t<T>[size]};
}
namespace bpstd {
namespace detail {
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
auto to_address_impl(const T& p, std::true_type)
-> decltype(std::pointer_traits<T>::to_address(std::declval<const T&>()))
{
return to_address(std::pointer_traits<T>::to_address(p));
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
auto to_address_impl(const T& p, std::false_type)
-> decltype(std::declval<const T&>().operator->())
{
return to_address(p.operator->());
}
} // namespace detail
} // namespace bpstd
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
T* bpstd::to_address(T* p)
noexcept
{
static_assert(
!std::is_function<T>::value,
"T* must not be a function pointer"
);
return p;
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::to_address_result_t<T>
bpstd::to_address(const T& p)
noexcept
{
return detail::to_address_impl(p, detail::has_to_address<T>{});
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_MEMORY_HPP */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,806 @@
////////////////////////////////////////////////////////////////////////////////
/// \file span.hpp
///
/// \brief This header provides definitions from the C++ header <span>
////////////////////////////////////////////////////////////////////////////////
/*
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 <cstddef> // std::size_t
#include <array> // std::array
#include <iterator> // std::iterator_traits
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
//============================================================================
// constants : dynamic_extent
//============================================================================
BPSTD_CPP17_INLINE constexpr auto dynamic_extent = static_cast<std::size_t>(-1);
namespace detail {
template <std::size_t Extent>
class extent_storage
{
public:
constexpr extent_storage() noexcept = default;
template <std::size_t UExtent>
constexpr explicit extent_storage(extent_storage<UExtent>)
{
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<dynamic_extent>
{
public:
template <std::size_t Extent>
constexpr explicit extent_storage(extent_storage<Extent> 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 <typename T, std::size_t Extent>
class span_storage_type : public extent_storage<Extent>
{
//------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------
public:
template <typename ExtentType>
constexpr span_storage_type(T* data, ExtentType ext)
: extent_storage<Extent>(ext),
m_data{data}
{
}
//------------------------------------------------------------------------
// Observers
//------------------------------------------------------------------------
public:
using extent_storage<Extent>::size;
constexpr T* data() const noexcept { return m_data; }
//------------------------------------------------------------------------
// Private Members
//------------------------------------------------------------------------
private:
T* m_data;
};
template <std::size_t From, std::size_t To>
struct is_allowed_extent_conversion
: bool_constant<(From == To) || (To == dynamic_extent)>{};
template <std::size_t Extent, std::size_t Offset, std::size_t Count>
struct compute_subspan_size
: integral_constant<std::size_t,
(Count != dynamic_extent)
? Count
: ((Extent != dynamic_extent) ? (Extent - Offset) : Extent)
>{};
template <typename It>
using iter_reference = typename std::iterator_traits<It>::reference;
template <typename It, typename T>
using is_iter_convertible = conjunction<
is_same<remove_cvref_t<iter_reference<It>>,remove_cv_t<T>>,
is_convertible<iter_reference<It>,remove_cv_t<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 <typename T, std::size_t Extent = dynamic_extent>
class span
{
//--------------------------------------------------------------------------
// Public Member Types
//--------------------------------------------------------------------------
public:
using element_type = T;
using value_type = remove_cv_t<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<T*,detail::span_storage_type<T,Extent>>;
using reverse_iterator = std::reverse_iterator<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 <std::size_t UExtent = Extent,
typename = enable_if_t<detail::is_allowed_extent_conversion<0,UExtent>::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 <typename It,
enable_if_t<(Extent == bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value,int> = 0>
constexpr span(It it, size_type count) noexcept;
template <typename It,
enable_if_t<(Extent != bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::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 <typename It, typename End,
enable_if_t<(Extent == bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value, int> = 0>
constexpr span(It it, End end) noexcept;
template <typename It, typename End,
enable_if_t<(Extent != bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::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 <std::size_t N,
typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::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 <typename U, std::size_t N,
typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
// cppcheck-suppress noExplicitConstructor
constexpr span(std::array<U, N>& arr) noexcept;
template <typename U, std::size_t N,
typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
// cppcheck-suppress noExplicitConstructor
constexpr span(const std::array<U, N>& 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 <typename U, std::size_t N,
typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
// cppcheck-suppress noExplicitConstructor
constexpr span(const span<U, N>& 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 <std::size_t Count>
constexpr span<element_type, Count> 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<element_type> 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 <std::size_t Count>
constexpr span<element_type, Count> 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<element_type> 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 <std::size_t Offset, std::size_t Count = dynamic_extent>
constexpr span<element_type, detail::compute_subspan_size<Extent,Offset,Count>::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<element_type> 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<element_type,Extent>;
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 <typename T, std::size_t N>
span<const byte, sizeof(T) * N> as_bytes(span<T, N> 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 <typename T, std::size_t N>
span<byte, sizeof(T) * N> as_writable_bytes(span<T, N> s) noexcept;
} // namespace bpstd
template <typename T, std::size_t Extent>
constexpr std::size_t bpstd::span<T,Extent>::extent;
//==============================================================================
// non-member functions : class : span
//==============================================================================
//------------------------------------------------------------------------------
// Constructors
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
template <std::size_t UExtent, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span()
noexcept
: m_storage{nullptr, detail::extent_storage<0>{}}
{
}
template <typename T, std::size_t Extent>
template <typename It,
bpstd::enable_if_t<(Extent == bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value,int>>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(It it, size_type count)
noexcept
: m_storage{to_address(it), count}
{
}
template <typename T, std::size_t Extent>
template <typename It,
bpstd::enable_if_t<(Extent != bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value,int>>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(It it, size_type count)
noexcept
: m_storage{to_address(it), count}
{
}
template <typename T, std::size_t Extent>
template <typename It, typename End,
bpstd::enable_if_t<(Extent == bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value, int>>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(It it, End end)
noexcept
: m_storage{to_address(it), static_cast<size_type>(end - it)}
{
}
template <typename T, std::size_t Extent>
template <typename It, typename End,
bpstd::enable_if_t<(Extent != bpstd::dynamic_extent) &&
bpstd::detail::is_iter_convertible<It, T>::value, int>>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(It it, End end)
noexcept
: m_storage{to_address(it), static_cast<size_type>(end - it)}
{
}
template <typename T, std::size_t Extent>
template <std::size_t N, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(element_type (&arr)[N])
noexcept
: m_storage{static_cast<element_type*>(arr), detail::extent_storage<N>{}}
{
}
template <typename T, std::size_t Extent>
template <typename U, std::size_t N, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(std::array<U, N>& arr)
noexcept
: m_storage{arr.data(), detail::extent_storage<N>{}}
{
}
template <typename T, std::size_t Extent>
template <typename U, std::size_t N, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(const std::array<U, N>& arr)
noexcept
: m_storage{arr.data(), detail::extent_storage<N>{}}
{
}
template <typename T, std::size_t Extent>
template <typename U, std::size_t N, typename>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<T,Extent>::span(const span<U, N>& s)
noexcept
: m_storage{s.data(), detail::extent_storage<N>{s.size()}}
{
}
//------------------------------------------------------------------------------
// Element Access
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::reference
bpstd::span<T,Extent>::front()
const noexcept
{
return data()[0];
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::reference
bpstd::span<T,Extent>::back()
const noexcept
{
return data()[m_storage.size()-1];
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::reference
bpstd::span<T,Extent>::operator[](size_type idx)
const noexcept
{
return data()[idx];
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::pointer
bpstd::span<T,Extent>::data()
const noexcept
{
return m_storage.data();
}
//------------------------------------------------------------------------------
// Observers
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::size_type
bpstd::span<T,Extent>::size()
const noexcept
{
return m_storage.size();
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::size_type
bpstd::span<T,Extent>::size_bytes()
const noexcept
{
return size() * sizeof(T);
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
bool bpstd::span<T,Extent>::empty()
const noexcept
{
return size() == 0u;
}
//------------------------------------------------------------------------------
// Subviews
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
template <std::size_t Count>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type, Count>
bpstd::span<T, Extent>::first()
const
{
static_assert(
Count <= Extent,
"A Count larger than Extent is ill-formed"
);
return span<element_type, Count>{data(), Count};
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type>
bpstd::span<T,Extent>::first(size_t count)
const
{
return {data(), count};
}
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
template <std::size_t Count>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type, Count>
bpstd::span<T, Extent>::last()
const
{
static_assert(
Count <= Extent,
"A Count larger than Extent is ill-formed"
);
return span<element_type, Count>{data() + (size() - Count), Count};
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type>
bpstd::span<T,Extent>::last(size_t count)
const
{
return {data() + (size() - count), count};
}
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
template <std::size_t Offset, std::size_t Count>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type, bpstd::detail::compute_subspan_size<Extent,Offset,Count>::value>
bpstd::span<T, Extent>::subspan()
const
{
using result_type = span<
element_type,
detail::compute_subspan_size<Extent,Offset,Count>::value
>;
return result_type{
data() + Offset,
(Count == dynamic_extent) ? (size() - Offset) : Count
};
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::span<typename bpstd::span<T, Extent>::element_type>
bpstd::span<T, Extent>::subspan(std::size_t offset, std::size_t count)
const
{
return {
data() + offset,
(count == dynamic_extent) ? (size() - offset) : count
};
}
//------------------------------------------------------------------------------
// Iterators
//------------------------------------------------------------------------------
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::iterator
bpstd::span<T,Extent>::begin()
const noexcept
{
return iterator{data()};
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::iterator
bpstd::span<T,Extent>::end()
const noexcept
{
return iterator{data() + size()};
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::reverse_iterator
bpstd::span<T,Extent>::rbegin()
const noexcept
{
return reverse_iterator(end());
}
template <typename T, std::size_t Extent>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::span<T,Extent>::reverse_iterator
bpstd::span<T,Extent>::rend()
const noexcept
{
return reverse_iterator(begin());
}
//==============================================================================
// non-member functions : class : span
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename T, std::size_t N>
inline bpstd::span<const bpstd::byte, sizeof(T) * N> bpstd::as_bytes(span<T, N> s)
noexcept
{
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}
template <typename T, std::size_t N>
inline bpstd::span<bpstd::byte, sizeof(T) * N> bpstd::as_writable_bytes(span<T, N> s)
noexcept
{
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_SPAN_HPP */

View File

@ -0,0 +1,84 @@
////////////////////////////////////////////////////////////////////////////////
/// \file string.hpp
///
/// \brief This header provides definitions from the C++ header <string>
////////////////////////////////////////////////////////////////////////////////
/*
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 <string>
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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
////////////////////////////////////////////////////////////////////////////////
/// \file tuple.hpp
///
/// \brief This header provides definitions from the C++ header <tuple>
////////////////////////////////////////////////////////////////////////////////
/*
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 <tuple> // std::tuple_element, and to proxy API
#include <cstddef> // std::size_t
BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
namespace bpstd {
//============================================================================
// class : tuple
//============================================================================
template <typename...Types>
using tuple = std::tuple<Types...>;
//============================================================================
// utilities : tuple
//============================================================================
template <std::size_t I, typename T>
using tuple_element = std::tuple_element<I,T>;
template <std::size_t I, typename T>
using tuple_element_t = typename tuple_element<I, T>::type;
//----------------------------------------------------------------------------
template <typename T>
using tuple_size = std::tuple_size<T>;
#if BPSTD_HAS_TEMPLATE_VARIABLES
template <typename T>
BPSTD_CPP17_INLINE constexpr auto tuple_size_v = tuple_size<T>::value;
#endif
//============================================================================
// non-member functions : class : tuple
//============================================================================
//----------------------------------------------------------------------------
// Utilities
//----------------------------------------------------------------------------
namespace detail {
template <typename T>
struct is_tuple : false_type{};
template <typename...Types>
struct is_tuple<std::tuple<Types...>> : true_type{};
} // namespace detail
template <std::size_t N, typename Tuple,
typename = enable_if_t<detail::is_tuple<remove_cvref_t<Tuple>>::value && is_lvalue_reference<Tuple>::value>>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
tuple_element_t<N,remove_reference_t<Tuple>>&
get(Tuple&& t) noexcept
{
return std::get<N>(t);
}
template <std::size_t N, typename Tuple,
typename = enable_if_t<detail::is_tuple<remove_cvref_t<Tuple>>::value && !is_lvalue_reference<Tuple>::value>>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
tuple_element_t<N,remove_reference_t<Tuple>>&&
get(Tuple&& t) noexcept
{
return bpstd::move(std::get<N>(t));
}
template <typename T, typename... Types>
BPSTD_CPP14_CONSTEXPR T& get(tuple<Types...>& t) noexcept;
template <typename T, typename... Types>
BPSTD_CPP14_CONSTEXPR T&& get(tuple<Types...>&& t) noexcept;
template <typename T, typename... Types>
BPSTD_CPP14_CONSTEXPR const T& get(const tuple<Types...>& t) noexcept;
template <typename T, typename... Types>
BPSTD_CPP14_CONSTEXPR const T&& get(const tuple<Types...>&& t) noexcept;
//----------------------------------------------------------------------------
namespace detail {
// primary template left undefined
template <typename Fn, typename Seq, typename Tuple>
struct apply_result_impl;
template <typename Fn, std::size_t...Idx, typename Tuple>
struct apply_result_impl<Fn, index_sequence<Idx...>, Tuple>
: invoke_result<Fn, tuple_element_t<Idx, Tuple>...>{};
template <typename Fn, typename Tuple>
struct apply_result : apply_result_impl<
Fn,
make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>,
Tuple
>{};
template <typename Fn, typename Tuple>
using apply_result_t = typename apply_result<Fn, Tuple>::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 <typename Fn, typename Tuple>
constexpr detail::apply_result_t<Fn, Tuple> 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 <typename T, typename Tuple>
constexpr T make_from_tuple(Tuple&& tuple);
} // namespace bpstd
//==============================================================================
// definitions : non-member functions : class : tuple
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
namespace bpstd { namespace detail {
template <typename T, std::size_t Index, typename...Types>
struct index_of_impl;
template <typename T, std::size_t Index, typename Type0, typename...Types>
struct index_of_impl<T, Index, Type0, Types...>
: index_of_impl<T, Index + 1, Types...>{};
template <typename T, std::size_t Index, typename...Types>
struct index_of_impl<T, Index, T, Types...>
: integral_constant<std::size_t, Index>{};
template <typename T, typename...Types>
struct index_of : index_of_impl<T,0,Types...>{};
}} // namespace bpstd::detail
template <typename T, typename... Types>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
T& bpstd::get(tuple<Types...>& t)
noexcept
{
return std::get<detail::index_of<T,Types...>::value>(t);
}
template <typename T, typename... Types>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
T&& bpstd::get(tuple<Types...>&& t)
noexcept
{
return move(std::get<detail::index_of<T,Types...>::value>(t));
}
template <typename T, typename... Types>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
const T& bpstd::get(const tuple<Types...>& t)
noexcept
{
return std::get<detail::index_of<T,Types...>::value>(t);
}
template <typename T, typename... Types>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
const T&& bpstd::get(const tuple<Types...>&& t)
noexcept
{
return move(std::get<detail::index_of<T,Types...>::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 <typename Fn, typename Tuple, std::size_t... I>
inline BPSTD_INLINE_VISIBILITY constexpr
apply_result_t<Fn,Tuple> apply_impl(Fn&& fn, Tuple&& tuple, index_sequence<I...>)
{
return ::bpstd::invoke(
bpstd::forward<Fn>(fn),
std::get<I>(bpstd::forward<Tuple>(tuple))...
);
}
} // namespace detail
} // namespace bpstd
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
template <typename Fn, typename Tuple>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::detail::apply_result_t<Fn, Tuple> bpstd::apply(Fn&& fn, Tuple&& tuple)
{
return detail::apply_impl(
bpstd::forward<Fn>(fn),
bpstd::forward<Tuple>(tuple),
make_index_sequence<tuple_size<remove_reference_t<Tuple>>::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 <typename T, typename Tuple, std::size_t... I>
inline BPSTD_INLINE_VISIBILITY constexpr
T make_from_tuple_impl(Tuple&& tuple, index_sequence<I...>)
{
return T(std::get<I>(bpstd::forward<Tuple>(tuple))...);
}
} // namespace detail
} // namespace bpstd
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
template <typename T, typename Tuple>
inline BPSTD_INLINE_VISIBILITY constexpr
T bpstd::make_from_tuple(Tuple&& tuple)
{
return detail::make_from_tuple_impl<T>(
bpstd::forward<Tuple>(tuple),
make_index_sequence<tuple_size<remove_reference_t<Tuple>>::value>{}
);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_TUPLE_HPP */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,382 @@
////////////////////////////////////////////////////////////////////////////////
/// \file utility.hpp
///
/// \brief This header provides definitions from the C++ header <utility>
////////////////////////////////////////////////////////////////////////////////
/*
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 <utility> // to proxy the API
#include <cstddef> // 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<typename T>
struct in_place_type_t
{
explicit in_place_type_t() = default;
};
#if BPSTD_HAS_TEMPLATE_VARIABLES
template<typename T>
BPSTD_CPP17_INLINE constexpr in_place_type_t<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<std::size_t I> struct in_place_index_t
{
explicit in_place_index_t() = default;
};
#if BPSTD_HAS_TEMPLATE_VARIABLES
template<std::size_t I>
BPSTD_CPP17_INLINE constexpr in_place_index_t<I> 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 <typename T>
constexpr typename bpstd::conditional<
!bpstd::is_nothrow_move_constructible<T>::value && bpstd::is_copy_constructible<T>::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 <typename T>
constexpr add_const_t<T>& as_const(T& t) noexcept;
template <typename T>
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 <typename T, typename U = T>
BPSTD_CPP14_CONSTEXPR T exchange(T& obj, U&& new_value);
//============================================================================
// class : pair
//============================================================================
template <typename T, typename U>
using pair = std::pair<T,U>;
//============================================================================
// non-member functions : class : pair
//============================================================================
//----------------------------------------------------------------------------
// Utilities
//----------------------------------------------------------------------------
// C++11 does not implement const pair&&
template <std::size_t N, typename T, typename U>
constexpr conditional_t<N==0,T,U>& get(pair<T, U>& p) noexcept;
template <std::size_t N, typename T, typename U>
constexpr conditional_t<N==0,T,U>&& get(pair<T, U>&& p) noexcept;
template <std::size_t N, typename T, typename U>
constexpr const conditional_t<N==0,T,U>& get(const pair<T, U>& p) noexcept;
template <std::size_t N, typename T, typename U>
constexpr const conditional_t<N==0,T,U>&& get(const pair<T, U>&& p) noexcept;
template <typename T, typename U>
constexpr T& get(pair<T, U>& p) noexcept;
template <typename T, typename U>
constexpr T&& get(pair<T, U>&& p) noexcept;
template <typename T, typename U>
constexpr const T& get(const pair<T, U>& p) noexcept;
template <typename T, typename U>
constexpr const T&& get(const pair<T, U>&& p) noexcept;
template <typename T, typename U>
constexpr T& get(pair<U, T>& p) noexcept;
template <typename T, typename U>
constexpr const T& get(const pair<U, T>& p) noexcept;
template <typename T, typename U>
constexpr T&& get(pair<U, T>&& p) noexcept;
template <typename T, typename U>
constexpr const T&& get(const pair<U, T>&& p) noexcept;
//============================================================================
// struct : integer_sequence
//============================================================================
template <typename T, T... Ints>
struct integer_sequence
{
using value_type = T;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
template <std::size_t... Ints>
using index_sequence = integer_sequence<std::size_t, Ints...>;
namespace detail {
template <typename T, bool End, T N, T...Tails>
struct make_integer_sequence_impl
: make_integer_sequence_impl<T,((N-1) == T(0)), N-1, N-1, Tails...>{};
template <typename T, T N, T...Tails>
struct make_integer_sequence_impl<T, true, N, Tails...>
: type_identity<integer_sequence<T, Tails...>>{};
} // namespace detail
template <typename T, T N>
using make_integer_sequence
= typename detail::make_integer_sequence_impl<T, (N==T(0)), N>::type;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
template<typename... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
} // namespace bpstd
//==============================================================================
// non-member functions
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
typename bpstd::conditional<
!bpstd::is_nothrow_move_constructible<T>::value && bpstd::is_copy_constructible<T>::value,
const T&,
T&&
>::type bpstd::move_if_noexcept(T& x)
noexcept
{
using result_type = conditional_t<
!is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value,
const T&,
T&&
>;
return static_cast<result_type>(x);
}
template <typename T>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::add_const_t<T>& bpstd::as_const(T& t)
noexcept
{
return t;
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
T bpstd::exchange(T& obj, U&& new_value)
{
auto old_value = bpstd::move(obj);
obj = bpstd::forward<U>(new_value);
return old_value;
}
//==============================================================================
// definitions : non-member functions : class : pair
//==============================================================================
//------------------------------------------------------------------------------
// Utilities
//------------------------------------------------------------------------------
template <std::size_t N, typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::conditional_t<N==0,T,U>&
bpstd::get(pair<T, U>& p)
noexcept
{
static_assert(N<=1, "N must be either 0 or 1 for get<N>(pair<T,U>)");
return std::get<N>(p);
}
template <std::size_t N, typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
bpstd::conditional_t<N==0,T,U>&&
bpstd::get(pair<T, U>&& p)
noexcept
{
static_assert(N<=1, "N must be either 0 or 1 for get<N>(pair<T,U>)");
return move(std::get<N>(p));
}
template <std::size_t N, typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const bpstd::conditional_t<N==0,T,U>&
bpstd::get(const pair<T, U>& p)
noexcept
{
static_assert(N<=1, "N must be either 0 or 1 for get<N>(pair<T,U>)");
return std::get<N>(p);
}
template <std::size_t N, typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const bpstd::conditional_t<N==0,T,U>&&
bpstd::get(const pair<T, U>&& p)
noexcept
{
static_assert(N<=1, "N must be either 0 or 1 for get<N>(pair<T,U>)");
return move(std::get<N>(p));
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
T& bpstd::get(pair<T, U>& p)
noexcept
{
return p.first;
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const T& bpstd::get(const pair<T, U>& p)
noexcept
{
return p.first;
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
T&& bpstd::get(pair<T, U>&& p)
noexcept
{
return move(p.first);
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const T&& bpstd::get(const pair<T, U>&& p)
noexcept
{
return move(p.first);
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
T& bpstd::get(pair<U, T>& p)
noexcept
{
return p.second;
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const T& bpstd::get(const pair<U, T>& p)
noexcept
{
return p.second;
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
T&& bpstd::get(pair<U, T>&& p)
noexcept
{
return move(p.second);
}
template <typename T, typename U>
inline BPSTD_INLINE_VISIBILITY constexpr
const T&& bpstd::get(const pair<U, T>&& p)
noexcept
{
return move(p.second);
}
BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
#endif /* BPSTD_UTILITY_HPP */

File diff suppressed because it is too large Load Diff

View File

@ -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 \