Use git submodule for xtl

This commit is contained in:
Paul Romano 2020-01-12 16:41:32 -06:00
parent 02eeddcf48
commit 71ed680466
32 changed files with 5 additions and 15135 deletions

3
.gitmodules vendored
View file

@ -7,3 +7,6 @@
[submodule "vendor/xtensor"]
path = vendor/xtensor
url = https://github.com/xtensor-stack/xtensor.git
[submodule "vendor/xtl"]
path = vendor/xtl
url = https://github.com/xtensor-stack/xtl.git

View file

@ -369,6 +369,6 @@ install(FILES man/man1/openmc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
install(FILES LICENSE DESTINATION "${CMAKE_INSTALL_DOCDIR}" RENAME copyright)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# Copy headers for vendored dependencies (note that xtensor/xtl are handled
# Copy headers for vendored dependencies (note that all except faddeeva are handled
# separately since they are managed by CMake)
install(DIRECTORY vendor/faddeeva DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

1
vendor/xtl vendored Submodule

@ -0,0 +1 @@
Subproject commit f5d13e6c4f856becc178939365fcdcf9a657ffb5

View file

@ -1,130 +0,0 @@
############################################################################
# Copyright (c) 2017, Sylvain Corlay and Johan Mabille #
# #
# Distributed under the terms of the BSD 3-Clause License. #
# #
# The full license is in the file LICENSE, distributed with this software. #
############################################################################
cmake_minimum_required(VERSION 3.1)
project(xtl)
enable_testing()
set(XTL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
# Versioning
# ===========
file(STRINGS "${XTL_INCLUDE_DIR}/xtl/xtl_config.hpp" xtl_version_defines
REGEX "#define XTL_VERSION_(MAJOR|MINOR|PATCH)")
foreach(ver ${xtl_version_defines})
if(ver MATCHES "#define XTL_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
set(XTL_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
endif()
endforeach()
set(${PROJECT_NAME}_VERSION
${XTL_VERSION_MAJOR}.${XTL_VERSION_MINOR}.${XTL_VERSION_PATCH})
message(STATUS "xtl v${${PROJECT_NAME}_VERSION}")
# Dependencies
# ============
find_package(nlohmann_json QUIET)
# Build
# =====
set(XTL_HEADERS
${XTL_INCLUDE_DIR}/xtl/xany.hpp
${XTL_INCLUDE_DIR}/xtl/xbasic_fixed_string.hpp
${XTL_INCLUDE_DIR}/xtl/xbase64.hpp
${XTL_INCLUDE_DIR}/xtl/xclosure.hpp
${XTL_INCLUDE_DIR}/xtl/xcomplex.hpp
${XTL_INCLUDE_DIR}/xtl/xcomplex_sequence.hpp
${XTL_INCLUDE_DIR}/xtl/xspan.hpp
${XTL_INCLUDE_DIR}/xtl/xspan_impl.hpp
${XTL_INCLUDE_DIR}/xtl/xdynamic_bitset.hpp
${XTL_INCLUDE_DIR}/xtl/xfunctional.hpp
${XTL_INCLUDE_DIR}/xtl/xhash.hpp
${XTL_INCLUDE_DIR}/xtl/xhierarchy_generator.hpp
${XTL_INCLUDE_DIR}/xtl/xiterator_base.hpp
${XTL_INCLUDE_DIR}/xtl/xjson.hpp
${XTL_INCLUDE_DIR}/xtl/xmasked_value_meta.hpp
${XTL_INCLUDE_DIR}/xtl/xmasked_value.hpp
${XTL_INCLUDE_DIR}/xtl/xmeta_utils.hpp
${XTL_INCLUDE_DIR}/xtl/xoptional_meta.hpp
${XTL_INCLUDE_DIR}/xtl/xoptional.hpp
${XTL_INCLUDE_DIR}/xtl/xoptional_sequence.hpp
${XTL_INCLUDE_DIR}/xtl/xproxy_wrapper.hpp
${XTL_INCLUDE_DIR}/xtl/xsequence.hpp
${XTL_INCLUDE_DIR}/xtl/xtl_config.hpp
${XTL_INCLUDE_DIR}/xtl/xtype_traits.hpp
${XTL_INCLUDE_DIR}/xtl/xvariant.hpp
${XTL_INCLUDE_DIR}/xtl/xvariant_impl.hpp
)
add_library(xtl INTERFACE)
target_include_directories(xtl INTERFACE $<BUILD_INTERFACE:${XTL_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
# xtl requires C++14 support!
target_compile_features(xtl INTERFACE cxx_std_14)
option(BUILD_TESTS "xtl test suite" OFF)
option(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF)
option(XTL_DISABLE_EXCEPTIONS "Disable C++ exceptions" OFF)
if(DOWNLOAD_GTEST OR GTEST_SRC_DIR)
set(BUILD_TESTS ON)
endif()
if(BUILD_TESTS)
add_subdirectory(test)
endif()
# Installation
# ============
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(TARGETS xtl
EXPORT ${PROJECT_NAME}-targets)
# Makes the project importable from the build directory
export(EXPORT ${PROJECT_NAME}-targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
install(FILES ${XTL_HEADERS}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtl)
set(XTL_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE
STRING "install path for xtlConfig.cmake")
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
# xtl is header-only and does not depend on the architecture.
# Remove CMAKE_SIZEOF_VOID_P from xtlConfigVersion.cmake so that an xtlConfig.cmake
# generated for a 64 bit target can be used for 32 bit targets and vice versa.
set(_XTL_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
unset(CMAKE_SIZEOF_VOID_P)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION ${${PROJECT_NAME}_VERSION}
COMPATIBILITY AnyNewerVersion)
set(CMAKE_SIZEOF_VOID_P ${_XTL_CMAKE_SIZEOF_VOID_P})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
install(EXPORT ${PROJECT_NAME}-targets
FILE ${PROJECT_NAME}Targets.cmake
DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
configure_file(${PROJECT_NAME}.pc.in
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
@ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")

View file

@ -1,463 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_ANY_HPP
#define XTL_ANY_HPP
#include <stdexcept>
#include <type_traits>
#include <typeinfo>
#include "xtl/xmeta_utils.hpp"
namespace xtl
{
/**************************************
* Implementation of C++17's std::any *
**************************************/
// Copyright (c) 2016 Denilson das Mercês Amorim
//
// 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)
class bad_any_cast : public std::bad_cast
{
public:
const char* what() const noexcept override
{
return "bad any cast";
}
};
namespace detail {
inline static void check_any_cast(const void* p) {
if (p == nullptr) {
#if defined(XTL_NO_EXCEPTIONS)
std::fprintf(stderr, "bad_any_cast\n");
std::terminate();
#else
throw bad_any_cast();
#endif
}
}
} // namespace detail
class any final
{
public:
/// Constructs an object of type any with an empty state.
any()
: vtable(nullptr)
{
}
/// Constructs an object of type any with an equivalent state as other.
any(const any& rhs)
: vtable(rhs.vtable)
{
if (!rhs.empty())
{
rhs.vtable->copy(rhs.storage, this->storage);
}
}
/// Constructs an object of type any with a state equivalent to the original state of other.
/// rhs is left in a valid but otherwise unspecified state.
any(any&& rhs) noexcept
: vtable(rhs.vtable)
{
if (!rhs.empty())
{
rhs.vtable->move(rhs.storage, this->storage);
rhs.vtable = nullptr;
}
}
/// Same effect as this->clear().
~any()
{
this->clear();
}
/// Constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value).
///
/// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
/// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
any(ValueType&& value)
{
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
"T shall satisfy the CopyConstructible requirements.");
this->construct(std::forward<ValueType>(value));
}
/// Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
any& operator=(const any& rhs)
{
any(rhs).swap(*this);
return *this;
}
/// Has the same effect as any(std::move(rhs)).swap(*this).
///
/// The state of *this is equivalent to the original state of rhs and rhs is left in a valid
/// but otherwise unspecified state.
any& operator=(any&& rhs) noexcept
{
any(std::move(rhs)).swap(*this);
return *this;
}
/// Has the same effect as any(std::forward<ValueType>(value)).swap(*this). No effect if a exception is thrown.
///
/// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
/// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
any& operator=(ValueType&& value)
{
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
"T shall satisfy the CopyConstructible requirements.");
any(std::forward<ValueType>(value)).swap(*this);
return *this;
}
/// If not empty, destroys the contained object.
void clear() noexcept
{
if (!empty())
{
this->vtable->destroy(storage);
this->vtable = nullptr;
}
}
/// Returns true if *this has no contained object, otherwise false.
bool empty() const noexcept
{
return this->vtable == nullptr;
}
/// If *this has a contained object of type T, typeid(T); otherwise typeid(void).
const std::type_info& type() const noexcept
{
return empty() ? typeid(void) : this->vtable->type();
}
/// Exchange the states of *this and rhs.
void swap(any& rhs) noexcept
{
if (this->vtable != rhs.vtable)
{
any tmp(std::move(rhs));
// move from *this to rhs.
rhs.vtable = this->vtable;
if (this->vtable != nullptr)
{
this->vtable->move(this->storage, rhs.storage);
//this->vtable = nullptr; -- uneeded, see below
}
// move from tmp (previously rhs) to *this.
this->vtable = tmp.vtable;
if (tmp.vtable != nullptr)
{
tmp.vtable->move(tmp.storage, this->storage);
tmp.vtable = nullptr;
}
}
else // same types
{
if (this->vtable != nullptr)
this->vtable->swap(this->storage, rhs.storage);
}
}
private: // Storage and Virtual Method Table
union storage_union {
using stack_storage_t = typename std::aligned_storage<2 * sizeof(void*), std::alignment_of<void*>::value>::type;
void* dynamic;
stack_storage_t stack; // 2 words for e.g. shared_ptr
};
/// Base VTable specification.
struct vtable_type
{
// Note: The caller is responssible for doing .vtable = nullptr after destructful operations
// such as destroy() and/or move().
/// The type of the object this vtable is for.
const std::type_info& (*type)() noexcept;
/// Destroys the object in the union.
/// The state of the union after this call is unspecified, caller must ensure not to use src anymore.
void (*destroy)(storage_union&) noexcept;
/// Copies the **inner** content of the src union into the yet unitialized dest union.
/// As such, both inner objects will have the same state, but on separate memory locations.
void (*copy)(const storage_union& src, storage_union& dest);
/// Moves the storage from src to the yet unitialized dest union.
/// The state of src after this call is unspecified, caller must ensure not to use src anymore.
void (*move)(storage_union& src, storage_union& dest) noexcept;
/// Exchanges the storage between lhs and rhs.
void (*swap)(storage_union& lhs, storage_union& rhs) noexcept;
};
/// VTable for dynamically allocated storage.
template <typename T>
struct vtable_dynamic
{
static const std::type_info& type() noexcept
{
return typeid(T);
}
static void destroy(storage_union& storage) noexcept
{
//assert(reinterpret_cast<T*>(storage.dynamic));
delete reinterpret_cast<T*>(storage.dynamic);
}
static void copy(const storage_union& src, storage_union& dest)
{
dest.dynamic = new T(*reinterpret_cast<const T*>(src.dynamic));
}
static void move(storage_union& src, storage_union& dest) noexcept
{
dest.dynamic = src.dynamic;
src.dynamic = nullptr;
}
static void swap(storage_union& lhs, storage_union& rhs) noexcept
{
// just exchage the storage pointers.
std::swap(lhs.dynamic, rhs.dynamic);
}
};
/// VTable for stack allocated storage.
template <typename T>
struct vtable_stack
{
static const std::type_info& type() noexcept
{
return typeid(T);
}
static void destroy(storage_union& storage) noexcept
{
reinterpret_cast<T*>(&storage.stack)->~T();
}
static void copy(const storage_union& src, storage_union& dest)
{
new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
}
static void move(storage_union& src, storage_union& dest) noexcept
{
// one of the conditions for using vtable_stack is a nothrow move constructor,
// so this move constructor will never throw a exception.
new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
destroy(src);
}
static void swap(storage_union& lhs, storage_union& rhs) noexcept
{
storage_union tmp_storage;
move(rhs, tmp_storage);
move(lhs, rhs);
move(tmp_storage, lhs);
}
};
/// Whether the type T must be dynamically allocated or can be stored on the stack.
template <typename T>
struct requires_allocation : std::integral_constant<bool,
!(std::is_nothrow_move_constructible<T>::value // N4562 <20>6.3/3 [any.class]
&& sizeof(T) <= sizeof(storage_union::stack) && std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
{
};
/// Returns the pointer to the vtable of the type T.
template <typename T>
static vtable_type* vtable_for_type()
{
using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
static vtable_type table = {
VTableType::type, VTableType::destroy,
VTableType::copy, VTableType::move,
VTableType::swap,
};
return &table;
}
protected:
template <typename T>
friend const T* any_cast(const any* operand) noexcept;
template <typename T>
friend T* any_cast(any* operand) noexcept;
/// Same effect as is_same(this->type(), t);
bool is_typed(const std::type_info& t) const
{
return is_same(this->type(), t);
}
/// Checks if two type infos are the same.
///
/// If ANY_IMPL_FAST_TYPE_INFO_COMPARE is defined, checks only the address of the
/// type infos, otherwise does an actual comparision. Checking addresses is
/// only a valid approach when there's no interaction with outside sources
/// (other shared libraries and such).
static bool is_same(const std::type_info& a, const std::type_info& b)
{
#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
return &a == &b;
#else
return a == b;
#endif
}
/// Casts (with no type_info checks) the storage pointer as const T*.
template <typename T>
const T* cast() const noexcept
{
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<const T*>(storage.dynamic) : reinterpret_cast<const T*>(&storage.stack);
}
/// Casts (with no type_info checks) the storage pointer as T*.
template <typename T>
T* cast() noexcept
{
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<T*>(storage.dynamic) : reinterpret_cast<T*>(&storage.stack);
}
private:
storage_union storage; // on offset(0) so no padding for align
vtable_type* vtable;
/// Chooses between stack and dynamic allocation for the type decay_t<ValueType>,
/// assigns the correct vtable, and constructs the object on our storage.
template <typename ValueType>
void construct(ValueType&& value)
{
using T = typename std::decay<ValueType>::type;
this->vtable = vtable_for_type<T>();
return xtl::mpl::static_if<requires_allocation<T>::value>([&](auto self)
{
self(*this).storage.dynamic = new T(std::forward<ValueType>(value));
}, /*else*/ [&](auto self)
{
new (&self(*this).storage.stack) T(std::forward<ValueType>(value));
});
}
};
namespace detail
{
template <typename ValueType>
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::true_type)
{
return std::move(*p);
}
template <typename ValueType>
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::false_type)
{
return *p;
}
}
/// Performs *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand), or throws bad_any_cast on failure.
template <typename ValueType>
inline ValueType any_cast(const any& operand)
{
auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
detail::check_any_cast(p);
return *p;
}
/// Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
template <typename ValueType>
inline ValueType any_cast(any& operand)
{
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
detail::check_any_cast(p);
return *p;
}
///
/// If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies:
/// Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
///
/// If ANY_IMPL_ANYCAST_MOVEABLE is defined, does as LWG Defect 2509 specifies:
/// If ValueType is MoveConstructible and isn't a lvalue reference, performs
/// std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise
/// *any_cast<remove_reference_t<ValueType>>(&operand). Throws bad_any_cast on failure.
///
template <typename ValueType>
inline ValueType any_cast(any&& operand)
{
#ifdef ANY_IMPL_ANY_CAST_MOVEABLE
// https://cplusplus.github.io/LWG/lwg-active.html#2509
using can_move = std::integral_constant<bool,
std::is_move_constructible<ValueType>::value && !std::is_lvalue_reference<ValueType>::value>;
#else
using can_move = std::false_type;
#endif
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
detail::check_any_cast(p);
return detail::any_cast_move_if_true<ValueType>(p, can_move());
}
/// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
/// contained by operand, otherwise nullptr.
template <typename T>
inline const T* any_cast(const any* operand) noexcept
{
if (operand == nullptr || !operand->is_typed(typeid(T)))
return nullptr;
else
return operand->cast<T>();
}
/// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
/// contained by operand, otherwise nullptr.
template <typename T>
inline T* any_cast(any* operand) noexcept
{
if (operand == nullptr || !operand->is_typed(typeid(T)))
return nullptr;
else
return operand->cast<T>();
}
}
namespace std
{
inline void swap(xtl::any& lhs, xtl::any& rhs) noexcept
{
lhs.swap(rhs);
}
}
#endif

View file

@ -1,76 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_BASE64_HPP
#define XTL_BASE64_HPP
#include <array>
#include <cstddef>
#include <string>
#include "xsequence.hpp"
namespace xtl
{
inline std::string base64decode(const std::string& input)
{
std::array<int, 256> T;
T.fill(-1);
for (std::size_t i = 0; i < 64; ++i)
{
T[std::size_t("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i])] = int(i);
}
std::string output;
int val = 0;
int valb = -8;
for (char c : input)
{
if (T[std::size_t(c)] == -1)
{
break;
}
val = (val << 6) + T[std::size_t(c)];
valb += 6;
if (valb >= 0)
{
output.push_back(char((val >> valb) & 0xFF));
valb -= 8;
}
}
return output;
}
inline std::string base64encode(const std::string& input)
{
std::string output;
int val = 0;
int valb = -6;
for (char sc : input)
{
unsigned char c = static_cast<unsigned char>(sc);
val = (val << 8) + c;
valb += 8;
while (valb >= 0)
{
output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]);
valb -= 6;
}
}
if (valb > -6)
{
output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]);
}
while (output.size() % 4)
{
output.push_back('=');
}
return output;
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,434 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_CLOSURE_HPP
#define XTL_CLOSURE_HPP
#include <memory>
#include <type_traits>
#include <utility>
#include "xtl_config.hpp"
namespace xtl
{
#ifdef __cpp_lib_as_const
using std::as_const;
#else
template <class T>
constexpr std::add_const_t<T>& as_const(T& t) noexcept
{
return t;
}
template <class T>
constexpr std::add_const_t<T&&>& as_const(T&& t) noexcept = delete;
#endif
/****************
* closure_type *
****************/
template <class S>
struct closure_type
{
using underlying_type = std::conditional_t<std::is_const<std::remove_reference_t<S>>::value,
const std::decay_t<S>,
std::decay_t<S>>;
using type = typename std::conditional<std::is_lvalue_reference<S>::value,
underlying_type&,
underlying_type>::type;
};
template <class S>
using closure_type_t = typename closure_type<S>::type;
template <class S>
struct const_closure_type
{
using underlying_type = std::decay_t<S>;
using type = typename std::conditional<std::is_lvalue_reference<S>::value,
std::add_const_t<underlying_type>&,
underlying_type>::type;
};
template <class S>
using const_closure_type_t = typename const_closure_type<S>::type;
/****************************
* ptr_closure_closure_type *
****************************/
template <class S>
struct ptr_closure_type
{
using underlying_type = std::conditional_t<std::is_const<std::remove_reference_t<S>>::value,
const std::decay_t<S>,
std::decay_t<S>>;
using type = std::conditional_t<std::is_lvalue_reference<S>::value,
underlying_type*,
underlying_type>;
};
template <class S>
using ptr_closure_type_t = typename ptr_closure_type<S>::type;
template <class S>
struct const_ptr_closure_type
{
using underlying_type = const std::decay_t<S>;
using type = std::conditional_t<std::is_lvalue_reference<S>::value,
underlying_type*,
underlying_type>;
};
template <class S>
using const_ptr_closure_type_t = typename const_ptr_closure_type<S>::type;
/********************
* xclosure_wrapper *
********************/
template <class CT>
class xclosure_wrapper
{
public:
using self_type = xclosure_wrapper<CT>;
using closure_type = CT;
using const_closure_type = std::add_const_t<CT>;
using value_type = std::decay_t<CT>;
using reference = std::conditional_t<
std::is_const<std::remove_reference_t<CT>>::value,
const value_type&, value_type&
>;
using pointer = std::conditional_t<
std::is_const<std::remove_reference_t<CT>>::value,
const value_type*, value_type*
>;
xclosure_wrapper(value_type&& e);
xclosure_wrapper(reference e);
xclosure_wrapper(const self_type& rhs) = default;
xclosure_wrapper(self_type&& rhs) = default;
self_type& operator=(const self_type& rhs);
self_type& operator=(self_type&& rhs);
template <class T>
self_type& operator=(T&&);
operator closure_type() noexcept;
operator const_closure_type() const noexcept;
std::add_lvalue_reference_t<closure_type> get() & noexcept;
std::add_lvalue_reference_t<std::add_const_t<closure_type>> get() const & noexcept;
closure_type get() && noexcept;
pointer operator&() noexcept;
bool equal(const self_type& rhs) const;
void swap(self_type& rhs);
private:
using storing_type = ptr_closure_type_t<CT>;
storing_type m_wrappee;
template <class T>
std::enable_if_t<std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
deref(T val) const;
template <class T>
std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<T>>
deref(T& val) const;
template <class T>
std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
get_pointer(T val) const;
template <class T>
std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_pointer_t<T>>
get_pointer(T& val) const;
template <class T, class CTA>
std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
get_storage_init(CTA&& e) const;
template <class T, class CTA>
std::enable_if_t<!std::is_lvalue_reference<CT>::value, T>
get_storage_init(CTA&& e) const;
};
// TODO: remove this (backward compatibility)
template <class CT>
using closure_wrapper = xclosure_wrapper<CT>;
/********************
* xclosure_pointer *
********************/
template <class CT>
class xclosure_pointer
{
public:
using self_type = xclosure_pointer<CT>;
using closure_type = CT;
using value_type = std::decay_t<CT>;
using reference = std::conditional_t<
std::is_const<std::remove_reference_t<CT>>::value,
const value_type&, value_type&
>;
using const_reference = const value_type&;
using pointer = std::conditional_t<
std::is_const<std::remove_reference_t<CT>>::value,
const value_type*, value_type*
>;
xclosure_pointer(value_type&& e);
xclosure_pointer(reference e);
reference operator*() noexcept;
const_reference operator*() const noexcept;
pointer operator->() const noexcept;
private:
using storing_type = closure_type_t<CT>;
storing_type m_wrappee;
};
/***********************************
* xclosure_wrapper implementation *
***********************************/
template <class CT>
inline xclosure_wrapper<CT>::xclosure_wrapper(value_type&& e)
: m_wrappee(get_storage_init<storing_type>(std::move(e)))
{
}
template <class CT>
inline xclosure_wrapper<CT>::xclosure_wrapper(reference e)
: m_wrappee(get_storage_init<storing_type>(e))
{
}
template <class CT>
inline auto xclosure_wrapper<CT>::operator=(const self_type& rhs) -> self_type&
{
deref(m_wrappee) = deref(rhs.m_wrappee);
return *this;
}
template <class CT>
inline auto xclosure_wrapper<CT>::operator=(self_type&& rhs) -> self_type&
{
swap(rhs);
return *this;
}
template <class CT>
template <class T>
inline auto xclosure_wrapper<CT>::operator=(T&& t) -> self_type&
{
deref(m_wrappee) = std::forward<T>(t);
return *this;
}
template <class CT>
inline xclosure_wrapper<CT>::operator typename xclosure_wrapper<CT>::closure_type() noexcept
{
return deref(m_wrappee);
}
template <class CT>
inline xclosure_wrapper<CT>::operator typename xclosure_wrapper<CT>::const_closure_type() const noexcept
{
return deref(m_wrappee);
}
template <class CT>
inline auto xclosure_wrapper<CT>::get() & noexcept -> std::add_lvalue_reference_t<closure_type>
{
return deref(m_wrappee);
}
template <class CT>
inline auto xclosure_wrapper<CT>::get() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<closure_type>>
{
return deref(m_wrappee);
}
template <class CT>
inline auto xclosure_wrapper<CT>::get() && noexcept -> closure_type
{
return deref(m_wrappee);
}
template <class CT>
inline auto xclosure_wrapper<CT>::operator&() noexcept -> pointer
{
return get_pointer(m_wrappee);
}
template <class CT>
template <class T>
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
xclosure_wrapper<CT>::deref(T val) const
{
return *val;
}
template <class CT>
template <class T>
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<T>>
xclosure_wrapper<CT>::deref(T& val) const
{
return val;
}
template <class CT>
template <class T>
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
xclosure_wrapper<CT>::get_pointer(T val) const
{
return val;
}
template <class CT>
template <class T>
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_pointer_t<T>>
xclosure_wrapper<CT>::get_pointer(T& val) const
{
return &val;
}
template <class CT>
template <class T, class CTA>
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
xclosure_wrapper<CT>::get_storage_init(CTA&& e) const
{
return &e;
}
template <class CT>
template <class T, class CTA>
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, T>
xclosure_wrapper<CT>::get_storage_init(CTA&& e) const
{
return e;
}
template <class CT>
inline bool xclosure_wrapper<CT>::equal(const self_type& rhs) const
{
return deref(m_wrappee) == rhs.deref(rhs.m_wrappee);
}
template <class CT>
inline void xclosure_wrapper<CT>::swap(self_type& rhs)
{
using std::swap;
swap(deref(m_wrappee), deref(rhs.m_wrappee));
}
template <class CT>
inline bool operator==(const xclosure_wrapper<CT>& lhs, const xclosure_wrapper<CT>& rhs)
{
return lhs.equal(rhs);
}
template <class CT>
inline bool operator!=(const xclosure_wrapper<CT>& lhs, const xclosure_wrapper<CT>& rhs)
{
return !(lhs == rhs);
}
template <class CT>
inline void swap(xclosure_wrapper<CT>& lhs, xclosure_wrapper<CT>& rhs)
{
lhs.swap(rhs);
}
/***********************************
* xclosure_pointer implementation *
***********************************/
template <class CT>
inline xclosure_pointer<CT>::xclosure_pointer(value_type&& e)
: m_wrappee(std::move(e))
{
}
template <class CT>
inline xclosure_pointer<CT>::xclosure_pointer(reference e)
: m_wrappee(e)
{
}
template <class CT>
inline auto xclosure_pointer<CT>::operator*() noexcept -> reference
{
return m_wrappee;
}
template <class CT>
inline auto xclosure_pointer<CT>::operator*() const noexcept -> const_reference
{
return m_wrappee;
}
template <class CT>
inline auto xclosure_pointer<CT>::operator->() const noexcept -> pointer
{
return const_cast<pointer>(std::addressof(m_wrappee));
}
/*****************************
* closure and const_closure *
*****************************/
template <class T>
inline decltype(auto) closure(T&& t)
{
return xclosure_wrapper<closure_type_t<T>>(std::forward<T>(t));
}
template <class T>
inline decltype(auto) const_closure(T&& t)
{
return xclosure_wrapper<const_closure_type_t<T>>(std::forward<T>(t));
}
/********************************************
* closure_pointer et const_closure_pointer *
********************************************/
template <class T>
inline auto closure_pointer(T&& t)
{
return xclosure_pointer<closure_type_t<T>>(std::forward<T>(t));
}
template <class T>
inline auto const_closure_pointer(T&& t)
{
return xclosure_pointer<const_closure_type_t<T>>(std::forward<T>(t));
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,577 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XCOMPLEX_SEQUENCE_HPP
#define XTL_XCOMPLEX_SEQUENCE_HPP
#include <array>
#include <vector>
#include <algorithm>
#include "xclosure.hpp"
#include "xcomplex.hpp"
#include "xiterator_base.hpp"
#include "xsequence.hpp"
namespace xtl
{
/************************************
* Optimized 1-D xcomplex container *
************************************/
template <class IT, bool ieee_compliant>
class xcomplex_iterator;
template <class C, bool ieee_compliant>
class xcomplex_sequence
{
public:
using container_type = C;
using cvt = typename C::value_type;
using value_type = xcomplex<cvt, cvt, ieee_compliant>;
using reference = xcomplex<cvt&, cvt&, ieee_compliant>;
using const_reference = xcomplex<const cvt&, const cvt&, ieee_compliant>;
using pointer = xclosure_pointer<reference>;
using const_pointer = xclosure_pointer<const_reference>;
using size_type = typename container_type::size_type;
using difference_type = typename container_type::difference_type;
using iterator = xcomplex_iterator<typename C::iterator, ieee_compliant>;
using const_iterator = xcomplex_iterator<typename C::const_iterator, ieee_compliant>;
using reverse_iterator = xcomplex_iterator<typename C::reverse_iterator, ieee_compliant>;
using const_reverse_iterator = xcomplex_iterator<typename C::const_reverse_iterator, ieee_compliant>;
bool empty() const noexcept;
size_type size() const noexcept;
size_type max_size() const noexcept;
reference at(size_type i);
const_reference at(size_type i) const;
reference operator[](size_type i);
const_reference operator[](size_type i) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
reverse_iterator rbegin() noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
container_type real() && noexcept;
container_type& real() & noexcept;
const container_type& real() const & noexcept;
container_type imag() && noexcept;
container_type& imag() & noexcept;
const container_type& imag() const & noexcept;
protected:
xcomplex_sequence() = default;
xcomplex_sequence(size_type s);
xcomplex_sequence(size_type s, const value_type& v);
template <class TR, class TC, bool B>
xcomplex_sequence(size_type s, const xcomplex<TR, TC, B>& v);
xcomplex_sequence(std::initializer_list<value_type> init);
~xcomplex_sequence() = default;
xcomplex_sequence(const xcomplex_sequence&) = default;
xcomplex_sequence& operator=(const xcomplex_sequence&) = default;
xcomplex_sequence(xcomplex_sequence&&) = default;
xcomplex_sequence& operator=(xcomplex_sequence&&) = default;
container_type m_real;
container_type m_imag;
};
template <class C, bool B>
bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
template <class C, bool B>
bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
/******************
* xcomplex_array *
******************/
template <class T, std::size_t N, bool ieee_compliant = false>
class xcomplex_array : public xcomplex_sequence<std::array<T, N>, ieee_compliant>
{
public:
using base_type = xcomplex_sequence<std::array<T, N>, ieee_compliant>;
using value_type = typename base_type::value_type;
using size_type = typename base_type::size_type;
xcomplex_array() = default;
xcomplex_array(size_type s);
xcomplex_array(size_type s, const value_type& v);
template <class TR, class TI, bool B>
xcomplex_array(size_type s, const xcomplex<TR, TI, B>& v);
};
/*******************
* xcomplex_vector *
*******************/
template <class T, bool ieee_compliant = false, class A = std::allocator<T>>
class xcomplex_vector : public xcomplex_sequence<std::vector<T, A>, ieee_compliant>
{
public:
using base_type = xcomplex_sequence<std::vector<T, A>, ieee_compliant>;
using value_type = typename base_type::value_type;
using size_type = typename base_type::size_type;
xcomplex_vector() = default;
xcomplex_vector(size_type s);
xcomplex_vector(size_type s, const value_type& v);
xcomplex_vector(std::initializer_list<value_type> init);
template <class TR, class TI, bool B>
xcomplex_vector(size_type s, const xcomplex<TR, TI, B>& v);
void resize(size_type);
void resize(size_type, const value_type&);
template <class TR, class TI, bool B>
void resize(size_type s, const xcomplex<TR, TI, B>& v);
};
/*********************
* xcomplex_iterator *
*********************/
template <class IT, bool ieee_compliant>
struct xcomplex_iterator_traits
{
using iterator_type = xcomplex_iterator<IT, ieee_compliant>;
using value_type = xcomplex<typename IT::value_type, typename IT::value_type, ieee_compliant>;
using reference = xcomplex<typename IT::reference, typename IT::reference, ieee_compliant>;
using pointer = xclosure_pointer<reference>;
using difference_type = typename IT::difference_type;
};
template <class IT, bool B>
class xcomplex_iterator : public xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>
{
public:
using self_type = xcomplex_iterator<IT, B>;
using base_type = xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>;
using value_type = typename base_type::value_type;
using reference = typename base_type::reference;
using pointer = typename base_type::pointer;
using difference_type = typename base_type::difference_type;
xcomplex_iterator() = default;
xcomplex_iterator(IT it_real, IT it_imag);
self_type& operator++();
self_type& operator--();
self_type& operator+=(difference_type n);
self_type& operator-=(difference_type n);
difference_type operator-(const self_type& rhs) const;
reference operator*() const;
pointer operator->() const;
bool operator==(const self_type& rhs) const;
private:
IT m_it_real;
IT m_it_imag;
};
/************************************
* xcomplex_sequence implementation *
************************************/
template <class C, bool B>
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s)
: m_real(make_sequence<container_type>(s)),
m_imag(make_sequence<container_type>(s))
{
}
template <class C, bool B>
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const value_type& v)
: m_real(make_sequence<container_type>(s, v.real())),
m_imag(make_sequence<container_type>(s, v.imag()))
{
}
template <class C, bool B>
template <class TR, class TC, bool B2>
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const xcomplex<TR, TC, B2>& v)
: m_real(make_sequence<container_type>(s, v.real())),
m_imag(make_sequence<container_type>(s, v.imag()))
{
}
template <class C, bool B>
inline xcomplex_sequence<C, B>::xcomplex_sequence(std::initializer_list<value_type> init)
: m_real(make_sequence<container_type>(init.size())),
m_imag(make_sequence<container_type>(init.size()))
{
std::transform(init.begin(), init.end(), m_real.begin(), [](const auto& v) { return v.real(); });
std::transform(init.begin(), init.end(), m_imag.begin(), [](const auto& v) { return v.imag(); });
}
template <class C, bool B>
inline bool xcomplex_sequence<C, B>::empty() const noexcept
{
return m_real.empty();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::size() const noexcept -> size_type
{
return m_real.size();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::max_size() const noexcept -> size_type
{
return m_real.max_size();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::at(size_type i) -> reference
{
return reference(m_real.at(i), m_imag.at(i));
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::at(size_type i) const -> const_reference
{
return const_reference(m_real.at(i), m_imag.at(i));
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::operator[](size_type i) -> reference
{
return reference(m_real[i], m_imag[i]);
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::operator[](size_type i) const -> const_reference
{
return const_reference(m_real[i], m_imag[i]);
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::front() -> reference
{
return reference(m_real.front(), m_imag.front());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::front() const -> const_reference
{
return const_reference(m_real.front(), m_imag.front());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::back() -> reference
{
return reference(m_real.back(), m_imag.back());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::back() const -> const_reference
{
return const_reference(m_real.back(), m_imag.back());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::begin() noexcept -> iterator
{
return iterator(m_real.begin(), m_imag.begin());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::end() noexcept -> iterator
{
return iterator(m_real.end(), m_imag.end());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::begin() const noexcept -> const_iterator
{
return cbegin();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::end() const noexcept -> const_iterator
{
return cend();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::cbegin() const noexcept -> const_iterator
{
return const_iterator(m_real.cbegin(), m_imag.cbegin());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::cend() const noexcept -> const_iterator
{
return const_iterator(m_real.cend(), m_imag.cend());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::rbegin() noexcept -> reverse_iterator
{
return reverse_iterator(m_real.rbegin(), m_imag.rbegin());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::rend() noexcept -> reverse_iterator
{
return reverse_iterator(m_real.rend(), m_imag.rend());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::rbegin() const noexcept -> const_reverse_iterator
{
return crbegin();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::rend() const noexcept -> const_reverse_iterator
{
return crend();
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::crbegin() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(m_real.crbegin(), m_imag.crbegin());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::crend() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(m_real.crend(), m_imag.crend());
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::real() && noexcept -> container_type
{
return m_real;
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::real() & noexcept -> container_type&
{
return m_real;
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::real() const & noexcept -> const container_type&
{
return m_real;
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::imag() && noexcept -> container_type
{
return m_imag;
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::imag() & noexcept -> container_type&
{
return m_imag;
}
template <class C, bool B>
inline auto xcomplex_sequence<C, B>::imag() const & noexcept -> const container_type&
{
return m_imag;
}
template <class C, bool B>
inline bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
{
return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
}
template <class C, bool B>
inline bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
{
return !(lhs == rhs);
}
/*********************************
* xcomplex_array implementation *
*********************************/
template <class T, std::size_t N, bool B>
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s)
: base_type(s)
{
}
template <class T, std::size_t N, bool B>
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const value_type& v)
: base_type(s, v)
{
}
template <class T, std::size_t N, bool B>
template <class TR, class TI, bool B2>
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const xcomplex<TR, TI, B2>& v)
: base_type(s, v)
{
}
/**********************************
* xcomplex_vector implementation *
**********************************/
template <class T, bool B, class A>
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s)
: base_type(s)
{
}
template <class T, bool B, class A>
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const value_type& v)
: base_type(s, v)
{
}
template <class T, bool B, class A>
template <class TR, class TI, bool B2>
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const xcomplex<TR, TI, B2>& v)
: base_type(s, v)
{
}
template <class T, bool B, class A>
inline xcomplex_vector<T, B, A>::xcomplex_vector(std::initializer_list<value_type> init)
: base_type(init)
{
}
template <class T, bool B, class A>
void xcomplex_vector<T, B, A>::resize(size_type s)
{
this->m_real.resize(s);
this->m_imag.resize(s);
}
template <class T, bool B, class A>
void xcomplex_vector<T, B, A>::resize(size_type s, const value_type& v)
{
this->m_real.resize(s, v.real());
this->m_imag.resize(s, v.imag());
}
template <class T, bool B, class A>
template <class TR, class TI, bool B2>
inline void xcomplex_vector<T, B, A>::resize(size_type s, const xcomplex<TR, TI, B2>& v)
{
this->m_real.resize(s, v.real());
this->m_imag.resize(s, v.imag());
}
/************************************
* xcomplex_iterator implementation *
************************************/
template <class IT, bool B>
inline xcomplex_iterator<IT, B>::xcomplex_iterator(IT it_real, IT it_imag)
: m_it_real(it_real), m_it_imag(it_imag)
{
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator++() -> self_type&
{
++m_it_real;
++m_it_imag;
return *this;
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator--() -> self_type&
{
--m_it_real;
--m_it_imag;
return *this;
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator+=(difference_type n) -> self_type&
{
m_it_real += n;
m_it_imag += n;
return *this;
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator-=(difference_type n) -> self_type&
{
m_it_real -= n;
m_it_imag -= n;
return *this;
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator-(const self_type& rhs) const -> difference_type
{
return m_it_real - rhs.m_it_real;
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator*() const -> reference
{
return reference(*m_it_real, *m_it_imag);
}
template <class IT, bool B>
inline auto xcomplex_iterator<IT, B>::operator->() const -> pointer
{
return pointer(operator*());
}
template <class IT, bool B>
inline bool xcomplex_iterator<IT, B>::operator==(const self_type& rhs) const
{
return m_it_real == rhs.m_it_real && m_it_imag == rhs.m_it_imag;
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,43 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_FUNCTIONAL_HPP
#define XTL_FUNCTIONAL_HPP
#include <utility>
#include "xtl_config.hpp"
#include "xtype_traits.hpp"
namespace xtl
{
/***************************
* identity implementation *
***************************/
struct identity
{
template <class T>
T&& operator()(T&& x) const
{
return std::forward<T>(x);
}
};
/*************************
* select implementation *
*************************/
template <class B, class T1, class T2, XTL_REQUIRES(all_scalar<B, T1, T2>)>
inline std::common_type_t<T1, T2> select(const B& cond, const T1& v1, const T2& v2) noexcept
{
return cond ? v1 : v2;
}
}
#endif

View file

@ -1,187 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_HASH_HPP
#define XTL_HASH_HPP
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace xtl
{
std::size_t hash_bytes(const void* buffer, std::size_t lenght, std::size_t seed);
/******************************
* hash_bytes implementation *
******************************/
namespace detail
{
// Dummy hash implementation for unusual sizeof(std::size_t)
template <std::size_t N>
std::size_t murmur_hash(const void* buffer, std::size_t length, std::size_t seed)
{
std::size_t hash = seed;
const char* data = static_cast<const char*>(buffer);
for (; length != 0; --length)
{
hash = (hash * 131) + static_cast<std::size_t>(*data++);
}
return hash;
}
// Murmur hash is an algorithm written by Austin Appleby. See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
template <>
inline std::size_t murmur_hash<4>(const void* buffer, std::size_t length, std::size_t seed)
{
constexpr std::size_t m = 0x5bd1e995;
std::size_t hash = seed ^ length;
const unsigned char* data = static_cast<const unsigned char*>(buffer);
// Mix 4 bytes at a time into the hash.
while (length >= 4)
{
std::size_t k;
std::memcpy(&k, data, sizeof(k));
k *= m;
k ^= k >> 24;
k *= m;
hash *= m;
hash ^= k;
data += 4;
length -= 4;
}
// Handle the last frwe bytes of the input array.
switch (length)
{
case 3:
hash ^= static_cast<std::size_t>(data[2] << 16);
case 2:
hash ^= static_cast<std::size_t>(data[1] << 8);
case 1:
hash ^= static_cast<std::size_t>(data[0]);
hash *= m;
}
// Do a few final mix of the hash to ensure the last few
// bytes are well-incorporated.
hash ^= hash >> 13;
hash *= m;
hash ^= hash >> 15;
return hash;
}
inline std::size_t load_bytes(const char* p, int n)
{
std::size_t result = 0;
--n;
do
{
result = (result << 8) + static_cast<unsigned char>(p[n]);
} while (--n >= 0);
return result;
}
#if INTPTR_MAX == INT64_MAX
// 64-bits hash for 64-bits platform
template <>
inline std::size_t murmur_hash<8>(const void* buffer, std::size_t length, std::size_t seed)
{
constexpr std::size_t m = (static_cast<std::size_t>(0xc6a4a793UL) << 32UL) +
static_cast<std::size_t>(0x5bd1e995UL);
constexpr int r = 47;
const char* data = static_cast<const char*>(buffer);
const char* end = data + (length & std::size_t(~0x7));
std::size_t hash = seed ^ (length * m);
while (data != end)
{
std::size_t k;
std::memcpy(&k, data, sizeof(k));
k *= m;
k ^= k >> r;
k *= m;
hash ^= k;
hash *= m;
data += 8;
}
if ((length & 0x7) != 0)
{
std::size_t k = load_bytes(end, length & 0x7);
hash ^= k;
hash *= m;
}
hash ^= hash >> r;
hash *= m;
hash ^= hash >> r;
return hash;
}
#elif INTPTR_MAX == INT32_MAX
//64-bits hash for 32-bits platform
inline void mmix(uint32_t& h, uint32_t& k, uint32_t m, int r)
{
k *= m; k ^= k >> r; k *= m; h *= m; h ^= k;
}
template <>
inline std::size_t murmur_hash<8>(const void* buffer, std::size_t length, std::size_t seed)
{
const uint32_t m = 0x5bd1e995;
const int r = 24;
uint32_t l = length;
const auto* data = reinterpret_cast<const unsigned char*>(buffer);
uint32_t h = seed;
while (length >= 4)
{
uint32_t k = *(uint32_t*)data;
mmix(h, k, m, r);
data += 4;
length -= 4;
}
uint32_t t = 0;
switch (length)
{
case 3: t ^= data[2] << 16;
case 2: t ^= data[1] << 8;
case 1: t ^= data[0];
};
mmix(h, t, m, r);
mmix(h, l, m, r);
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
#else
#error Unknown pointer size or missing size macros!
#endif
}
inline std::size_t hash_bytes(const void* buffer, std::size_t length, std::size_t seed)
{
return detail::murmur_hash<sizeof(std::size_t)>(buffer, length, seed);
}
}
#endif

View file

@ -1,72 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_HIERARCHY_GENERATOR_HPP
#define XTL_HIERARCHY_GENERATOR_HPP
#include "xmeta_utils.hpp"
namespace xtl
{
/*********************************
* scattered hierarchy generator *
*********************************/
template <class TL, template <class> class U>
class xscatter_hierarchy_generator;
template <template <class> class U, class T, class... Args>
class xscatter_hierarchy_generator<mpl::vector<T, Args...>, U>
: public U<T>, public xscatter_hierarchy_generator<mpl::vector<Args...>, U>
{
};
template <template <class> class U>
class xscatter_hierarchy_generator<mpl::vector<>, U>
{
};
/******************************
* linear hierarchy generator *
******************************/
class default_root {};
template <class TL, template <class, class> class U, class Root = default_root>
class xlinear_hierarchy_generator;
template <template <class, class> class U, class Root, class T0, class... Args>
class xlinear_hierarchy_generator<mpl::vector<T0, Args...>, U, Root>
: public U<T0, xlinear_hierarchy_generator<mpl::vector<Args...>, U, Root>>
{
public:
using base_type = U<T0, xlinear_hierarchy_generator<mpl::vector<Args...>, U, Root>>;
template <class... T>
inline xlinear_hierarchy_generator(T&&... args)
: base_type(std::forward<T>(args)...)
{
}
};
template <template <class, class> class U, class Root>
class xlinear_hierarchy_generator<mpl::vector<>, U, Root>
: public Root
{
public:
template <class... T>
inline xlinear_hierarchy_generator(T&&... args)
: Root(std::forward<T>(args)...)
{
}
};
}
#endif

View file

@ -1,231 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XITERATOR_BASE_HPP
#define XTL_XITERATOR_BASE_HPP
#include <cstddef>
#include <iterator>
namespace xtl
{
/**************************************
* class xbidirectional_iterator_base *
**************************************/
template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
class xbidirectional_iterator_base
{
public:
using derived_type = I;
using value_type = T;
using reference = R;
using pointer = P;
using difference_type = D;
using iterator_category = std::bidirectional_iterator_tag;
inline friend derived_type operator++(derived_type& d, int)
{
derived_type tmp(d);
++d;
return tmp;
}
inline friend derived_type operator--(derived_type& d, int)
{
derived_type tmp(d);
--d;
return tmp;
}
inline friend bool operator!=(const derived_type& lhs, const derived_type& rhs)
{
return !(lhs == rhs);
}
};
template <class T>
using xbidirectional_iterator_base2 = xbidirectional_iterator_base<typename T::iterator_type,
typename T::value_type,
typename T::difference_type,
typename T::pointer,
typename T::reference>;
/********************************
* xrandom_access_iterator_base *
********************************/
template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
class xrandom_access_iterator_base : public xbidirectional_iterator_base<I, T, D, P, R>
{
public:
using derived_type = I;
using value_type = T;
using reference = R;
using pointer = P;
using difference_type = D;
using iterator_category = std::random_access_iterator_tag;
inline reference operator[](difference_type n) const
{
return *(*static_cast<const derived_type*>(this) + n);
}
inline friend derived_type operator+(const derived_type& it, difference_type n)
{
derived_type tmp(it);
return tmp += n;
}
inline friend derived_type operator+(difference_type n, const derived_type& it)
{
derived_type tmp(it);
return tmp += n;
}
inline friend derived_type operator-(const derived_type& it, difference_type n)
{
derived_type tmp(it);
return tmp -= n;
}
inline friend bool operator<=(const derived_type& lhs, const derived_type& rhs)
{
return !(rhs < lhs);
}
inline friend bool operator>=(const derived_type& lhs, const derived_type& rhs)
{
return !(lhs < rhs);
}
inline friend bool operator>(const derived_type& lhs, const derived_type& rhs)
{
return rhs < lhs;
}
};
template <class T>
using xrandom_access_iterator_base2 = xrandom_access_iterator_base<typename T::iterator_type,
typename T::value_type,
typename T::difference_type,
typename T::pointer,
typename T::reference>;
/*******************************
* xrandom_access_iterator_ext *
*******************************/
// Extension for random access iterators defining operator[] and operator+ overloads
// accepting size_t arguments.
template <class I, class R>
class xrandom_access_iterator_ext
{
public:
using derived_type = I;
using reference = R;
using size_type = std::size_t;
inline reference operator[](size_type n) const
{
return *(*static_cast<const derived_type*>(this) + n);
}
inline friend derived_type operator+(const derived_type& it, size_type n)
{
derived_type tmp(it);
return tmp += n;
}
inline friend derived_type operator+(size_type n, const derived_type& it)
{
derived_type tmp(it);
return tmp += n;
}
inline friend derived_type operator-(const derived_type& it, size_type n)
{
derived_type tmp(it);
return tmp -= n;
}
};
/*****************
* xkey_iterator *
*****************/
template <class M>
class xkey_iterator : public xbidirectional_iterator_base<xkey_iterator<M>, const typename M::key_type>
{
public:
using self_type = xkey_iterator;
using base_type = xbidirectional_iterator_base<self_type, const typename M::key_type>;
using value_type = typename base_type::value_type;
using reference = typename base_type::reference;
using pointer = typename base_type::pointer;
using difference_type = typename base_type::difference_type;
using iterator_category = typename base_type::iterator_category;
using subiterator = typename M::const_iterator;
inline xkey_iterator(subiterator it) noexcept
: m_it(it)
{
}
inline self_type& operator++()
{
++m_it;
return *this;
}
inline self_type& operator--()
{
--m_it;
return *this;
}
inline reference operator*() const
{
return m_it->first;
}
inline pointer operator->() const
{
return&(m_it->first);
}
inline bool operator==(const self_type& rhs) const
{
return m_it == rhs.m_it;
}
private:
subiterator m_it;
};
/***********************
* common_iterator_tag *
***********************/
template <class... Its>
struct common_iterator_tag : std::common_type<typename std::iterator_traits<Its>::iterator_category...>
{
};
template <class... Its>
using common_iterator_tag_t = typename common_iterator_tag<Its...>::type;
}
#endif

View file

@ -1,76 +0,0 @@
#ifndef XTL_JSON_HPP
#define XTL_JSON_HPP
// WARNING:
// All the code in this file and in the
// files it includes must be C++11 compliant,
// otherwise it breaks xeus-cling C++11 kernel
#include <cstddef>
#include <string>
#include "nlohmann/json.hpp"
namespace xtl
{
/***********************************************************
* to_json and from_json specialization for xtl::xoptional *
***********************************************************/
// xoptional forward declaration.
template <class D, class B>
class xoptional;
template <class T>
xoptional<T, bool> missing() noexcept;
// to_json and from_json ADL overload
template <class D, class B>
void to_json(nlohmann::json& j, const xoptional<D, B>& o)
{
if (!o.has_value())
{
j = nullptr;
}
else
{
j = o.value();
}
}
template <class D, class B>
void from_json(const nlohmann::json& j, xoptional<D, B>& o)
{
if (j.is_null())
{
o = missing<D>();
}
else
{
o = j.get<D>();
}
}
/********************************************************************
* to_json and from_json specialization for xtl::basic_fixed_string *
********************************************************************/
// xbasic_fixed_string forward declaration.
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
class xbasic_fixed_string;
// to_json and from_json ADL overload
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
void to_json(::nlohmann::json& j, const xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
j = str.c_str();
}
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
void from_json(const ::nlohmann::json& j, xbasic_fixed_string<CT, N, ST, EP, TR>& str)
{
str = j.get<std::string>();
}
}
#endif

View file

@ -1,545 +0,0 @@
/***************************************************************************
* Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
* Martin Renou *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XMASKED_VALUE_HPP
#define XTL_XMASKED_VALUE_HPP
#include "xmasked_value_meta.hpp"
#include "xtype_traits.hpp"
namespace xtl
{
template <class T>
inline xmasked_value<T, bool> masked() noexcept
{
return xmasked_value<T, bool>(T(0), false);
}
/****************************
* xmasked_value declaration *
*****************************/
template <class T, class B>
class xmasked_value
{
public:
using self_type = xmasked_value<T, B>;
using value_type = T;
using flag_type = B;
template <class T1, class B1>
constexpr xmasked_value(T1&& value, B1&& flag);
template <class T1>
constexpr xmasked_value(T1&& value);
explicit constexpr xmasked_value();
inline operator value_type() {
return m_value;
}
std::add_lvalue_reference_t<T> value() & noexcept;
std::add_lvalue_reference_t<std::add_const_t<T>> value() const & noexcept;
std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>> value() && noexcept;
std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>> value() const && noexcept;
std::add_lvalue_reference_t<B> visible() & noexcept;
std::add_lvalue_reference_t<std::add_const_t<B>> visible() const & noexcept;
std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>> visible() && noexcept;
std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>> visible() const && noexcept;
template <class T1, class B1>
bool equal(const xmasked_value<T1, B1>& rhs) const noexcept;
template <class T1, XTL_DISALLOW(is_xmasked_value<T1>)>
bool equal(const T1& rhs) const noexcept;
template <class T1, class B1>
void swap(xmasked_value<T1, B1>& other);
#define DEFINE_ASSIGN_OPERATOR(OP) \
template <class T1> \
inline xmasked_value& operator OP(const T1& rhs) \
{ \
if (m_visible) \
{ \
m_value OP rhs; \
} \
return *this; \
} \
\
template <class T1, class B1> \
inline xmasked_value& operator OP(const xmasked_value<T1, B1>& rhs) \
{ \
m_visible = m_visible && rhs.visible(); \
if (m_visible) \
{ \
m_value OP rhs.value(); \
} \
return *this; \
}
DEFINE_ASSIGN_OPERATOR(=);
DEFINE_ASSIGN_OPERATOR(+=);
DEFINE_ASSIGN_OPERATOR(-=);
DEFINE_ASSIGN_OPERATOR(*=);
DEFINE_ASSIGN_OPERATOR(/=);
DEFINE_ASSIGN_OPERATOR(%=);
DEFINE_ASSIGN_OPERATOR(&=);
DEFINE_ASSIGN_OPERATOR(|=);
DEFINE_ASSIGN_OPERATOR(^=);
#undef DEFINE_ASSIGN_OPERATOR
private:
value_type m_value;
flag_type m_visible;
};
/********************************
* xmasked_value implementation *
********************************/
template <class T, class B>
template <class T1, class B1>
inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value, B1&& flag)
: m_value(std::forward<T1>(value)), m_visible(std::forward<B1>(flag))
{
}
template <class T, class B>
template <class T1>
inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value)
: m_value(std::forward<T1>(value)), m_visible(true)
{
}
template <class T, class B>
inline constexpr xmasked_value<T, B>::xmasked_value()
: m_value(0), m_visible(true)
{
}
template <class T>
inline auto masked_value(T&& val)
{
return xmasked_value<T>(std::forward<T>(val));
}
template <class T, class B>
inline auto masked_value(T&& val, B&& mask)
{
return xmasked_value<T, B>(std::forward<T>(val), std::forward<B>(mask));
}
template <class T, class B>
inline auto xmasked_value<T, B>::value() & noexcept -> std::add_lvalue_reference_t<T>
{
return m_value;
}
template <class T, class B>
inline auto xmasked_value<T, B>::value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<T>>
{
return m_value;
}
template <class T, class B>
inline auto xmasked_value<T, B>::value() && noexcept -> std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>>
{
return m_value;
}
template <class T, class B>
inline auto xmasked_value<T, B>::value() const && noexcept -> std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>>
{
return m_value;
}
template <class T, class B>
inline auto xmasked_value<T, B>::visible() & noexcept -> std::add_lvalue_reference_t<B>
{
return m_visible;
}
template <class T, class B>
inline auto xmasked_value<T, B>::visible() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<B>>
{
return m_visible;
}
template <class T, class B>
inline auto xmasked_value<T, B>::visible() && noexcept -> std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>>
{
return m_visible;
}
template <class T, class B>
inline auto xmasked_value<T, B>::visible() const && noexcept -> std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>>
{
return m_visible;
}
template <class T, class B>
template <class T1, class B1>
inline bool xmasked_value<T, B>::equal(const xmasked_value<T1, B1>& rhs) const noexcept
{
return (!m_visible && !rhs.visible()) || (m_value == rhs.value() && (m_visible && rhs.visible()));
}
template <class T, class B>
template <class T1, check_disallow<is_xmasked_value<T1>>>
inline bool xmasked_value<T, B>::equal(const T1& rhs) const noexcept
{
return m_visible && m_value == rhs;
}
template <class T, class B>
template <class T1, class B1>
inline void xmasked_value<T, B>::swap(xmasked_value<T1, B1>& other)
{
using std::swap;
swap(m_value, other.m_value);
swap(m_visible, other.m_visible);
}
template <class T1, class B1, class T2, class B2>
inline bool operator==(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
{
return lhs.equal(rhs);
}
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
inline bool operator==(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
{
return rhs.equal(lhs);
}
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
inline bool operator==(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
{
return lhs.equal(rhs);
}
template <class T1, class B1, class T2, class B2>
inline bool operator!=(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
{
return !lhs.equal(rhs);
}
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
inline bool operator!=(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
{
return !rhs.equal(lhs);
}
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
inline bool operator!=(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
{
return !lhs.equal(rhs);
}
template <class T, class B>
inline auto operator+(const xmasked_value<T, B>& e) noexcept
-> xmasked_value<std::decay_t<T>, std::decay_t<B>>
{
return xmasked_value<std::decay_t<T>, std::decay_t<B>>(e.value(), e.visible());
}
template <class T, class B>
inline auto operator-(const xmasked_value<T, B>& e) noexcept
-> xmasked_value<std::decay_t<T>, std::decay_t<B>>
{
return xmasked_value<std::decay_t<T>, std::decay_t<B>>(-e.value(), e.visible());
}
template <class T, class B>
inline auto operator~(const xmasked_value<T, B>& e) noexcept
-> xmasked_value<std::decay_t<T>>
{
using value_type = std::decay_t<T>;
return e.visible() ? masked_value(~e.value()) : masked<value_type>();
}
template <class T, class B>
inline auto operator!(const xmasked_value<T, B>& e) noexcept -> xmasked_value<decltype(!e.value())>
{
using return_type = xmasked_value<decltype(!e.value())>;
using value_type = typename return_type::value_type;
return e.visible() ? return_type(!e.value()) : masked<value_type>();
}
template <class T, class B, class OC, class OT>
inline std::basic_ostream<OC, OT>& operator<<(std::basic_ostream<OC, OT>& out, xmasked_value<T, B> v)
{
if (v.visible())
{
out << v.value();
}
else
{
out << "masked";
}
return out;
}
template <class T1, class B1, class T2, class B2>
inline void swap(xmasked_value<T1, B1>& lhs, xmasked_value<T2, B2>& rhs)
{
lhs.swap(rhs);
}
#define DEFINE_OPERATOR(OP) \
template <class T1, class B1, class T2, class B2> \
inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
{ \
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
return e1.visible() && e2.visible() ? masked_value(e1.value() OP e2.value()) : masked<value_type>(); \
} \
\
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
{ \
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
return e1.visible() ? masked_value(e1.value() OP e2) : masked<value_type>(); \
} \
\
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
{ \
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
return e2.visible() ? masked_value(e1 OP e2.value()) : masked<value_type>(); \
}
#define DEFINE_BOOL_OPERATOR(OP) \
template <class T1, class B1, class T2, class B2> \
inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
-> xmasked_value<decltype(e1.value() OP e2.value())> \
{ \
return e1.visible() && e2.visible() ? \
masked_value(e1.value() OP e2.value()) : \
masked<decltype(e1.value() OP e2.value())>(); \
} \
\
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
-> xmasked_value<decltype(e1.value() OP e2)> \
{ \
return e1.visible() ? masked_value(e1.value() OP e2) : masked<decltype(e1.value() OP e2)>(); \
} \
\
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
-> xmasked_value<decltype(e1 OP e2.value())> \
{ \
return e2.visible() ? masked_value(e1 OP e2.value()) : masked<decltype(e1 OP e2.value())>(); \
}
#define DEFINE_UNARY_OPERATOR(OP) \
template <class T, class B> \
inline xmasked_value<std::decay_t<T>> OP(const xmasked_value<T, B>& e) \
{ \
using std::OP; \
return e.visible() ? masked_value(OP(e.value())) : masked<std::decay_t<T>>(); \
}
#define DEFINE_UNARY_BOOL_OPERATOR(OP) \
template <class T, class B> \
inline auto OP(const xmasked_value<T, B>& e) \
{ \
using std::OP; \
return e.visible() ? masked_value(OP(e.value())) : masked<decltype(OP(e.value()))>(); \
}
#define DEFINE_BINARY_OPERATOR(OP) \
template <class T1, class B1, class T2, class B2> \
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) \
{ \
using std::OP; \
return e1.visible() && e2.visible() ? \
masked_value(OP(e1.value(), e2.value())) : \
masked<decltype(OP(e1.value(), e2.value()))>(); \
} \
\
template <class T1, class B1, class T2> \
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2) \
{ \
using std::OP; \
return e1.visible() ? masked_value(OP(e1.value(), e2)) : masked<decltype(OP(e1.value(), e2))>(); \
} \
\
template <class T1, class T2, class B2> \
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2) \
{ \
using std::OP; \
return e2.visible() ? masked_value(OP(e1, e2.value())) : masked<decltype(OP(e1, e2.value()))>(); \
}
#define DEFINE_TERNARY_OPERATOR_MMM(OP) \
template <class T1, class B1, class T2, class B2, class T3, class B3> \
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
{ \
using std::OP; \
return (e1.visible() && e2.visible() && e3.visible()) ? \
masked_value(OP(e1.value(), e2.value(), e3.value())) : \
masked<decltype(OP(e1.value(), e2.value(), e3.value()))>(); \
}
#define DEFINE_TERNARY_OPERATOR_MMT(OP) \
template <class T1, class B1, class T2, class B2, class T3> \
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
{ \
using std::OP; \
return (e1.visible() && e2.visible()) ? \
masked_value(OP(e1.value(), e2.value(), e3)) : \
masked<decltype(OP(e1.value(), e2.value(), e3))>(); \
}
#define DEFINE_TERNARY_OPERATOR_MTM(OP) \
template <class T1, class B1, class T2, class T3, class B3> \
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
{ \
using std::OP; \
return (e1.visible() && e3.visible()) ? \
masked_value(OP(e1.value(), e2, e3.value())) : \
masked<decltype(OP(e1.value(), e2, e3.value()))>(); \
}
#define DEFINE_TERNARY_OPERATOR_TMM(OP) \
template <class T1, class T2, class B2, class T3, class B3> \
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
{ \
using std::OP; \
return (e2.visible() && e3.visible()) ? \
masked_value(OP(e1, e2.value(), e3.value())) : \
masked<decltype(OP(e1, e2.value(), e3.value()))>(); \
}
#define DEFINE_TERNARY_OPERATOR_TTM(OP) \
template <class T1, class T2, class T3, class B3> \
inline auto OP(const T1& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
{ \
using std::OP; \
return e3.visible() ? \
masked_value(OP(e1, e2, e3.value())) : \
masked<decltype(OP(e1, e2, e3.value()))>(); \
}
#define DEFINE_TERNARY_OPERATOR_TMT(OP) \
template <class T1, class T2, class B2, class T3> \
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
{ \
using std::OP; \
return e2.visible() ? \
masked_value(OP(e1, e2.value(), e3)) : \
masked<decltype(OP(e1, e2.value(), e3))>(); \
}
#define DEFINE_TERNARY_OPERATOR_MTT(OP) \
template <class T1, class B1, class T2, class T3> \
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const T3& e3) \
{ \
using std::OP; \
return e1.visible() ? \
masked_value(OP(e1.value(), e2, e3)) : \
masked<decltype(OP(e1.value(), e2, e3))>(); \
}
#define DEFINE_TERNARY_OPERATOR(OP) \
DEFINE_TERNARY_OPERATOR_MMM(OP) \
\
DEFINE_TERNARY_OPERATOR_MMT(OP) \
DEFINE_TERNARY_OPERATOR_MTM(OP) \
DEFINE_TERNARY_OPERATOR_TMM(OP) \
DEFINE_TERNARY_OPERATOR_TTM(OP) \
DEFINE_TERNARY_OPERATOR_TMT(OP) \
DEFINE_TERNARY_OPERATOR_MTT(OP)
DEFINE_OPERATOR(+);
DEFINE_OPERATOR(-);
DEFINE_OPERATOR(*);
DEFINE_OPERATOR(/);
DEFINE_OPERATOR(%);
DEFINE_BOOL_OPERATOR(||);
DEFINE_BOOL_OPERATOR(&&);
DEFINE_OPERATOR(&);
DEFINE_OPERATOR(|);
DEFINE_OPERATOR(^);
DEFINE_BOOL_OPERATOR(<);
DEFINE_BOOL_OPERATOR(<=);
DEFINE_BOOL_OPERATOR(>);
DEFINE_BOOL_OPERATOR(>=);
DEFINE_UNARY_OPERATOR(abs)
DEFINE_UNARY_OPERATOR(fabs)
DEFINE_UNARY_OPERATOR(exp)
DEFINE_UNARY_OPERATOR(exp2)
DEFINE_UNARY_OPERATOR(expm1)
DEFINE_UNARY_OPERATOR(log)
DEFINE_UNARY_OPERATOR(log10)
DEFINE_UNARY_OPERATOR(log2)
DEFINE_UNARY_OPERATOR(log1p)
DEFINE_UNARY_OPERATOR(sqrt)
DEFINE_UNARY_OPERATOR(cbrt)
DEFINE_UNARY_OPERATOR(sin)
DEFINE_UNARY_OPERATOR(cos)
DEFINE_UNARY_OPERATOR(tan)
DEFINE_UNARY_OPERATOR(acos)
DEFINE_UNARY_OPERATOR(asin)
DEFINE_UNARY_OPERATOR(atan)
DEFINE_UNARY_OPERATOR(sinh)
DEFINE_UNARY_OPERATOR(cosh)
DEFINE_UNARY_OPERATOR(tanh)
DEFINE_UNARY_OPERATOR(acosh)
DEFINE_UNARY_OPERATOR(asinh)
DEFINE_UNARY_OPERATOR(atanh)
DEFINE_UNARY_OPERATOR(erf)
DEFINE_UNARY_OPERATOR(erfc)
DEFINE_UNARY_OPERATOR(tgamma)
DEFINE_UNARY_OPERATOR(lgamma)
DEFINE_UNARY_OPERATOR(ceil)
DEFINE_UNARY_OPERATOR(floor)
DEFINE_UNARY_OPERATOR(trunc)
DEFINE_UNARY_OPERATOR(round)
DEFINE_UNARY_OPERATOR(nearbyint)
DEFINE_UNARY_OPERATOR(rint)
DEFINE_UNARY_BOOL_OPERATOR(isfinite)
DEFINE_UNARY_BOOL_OPERATOR(isinf)
DEFINE_UNARY_BOOL_OPERATOR(isnan)
DEFINE_BINARY_OPERATOR(fmod)
DEFINE_BINARY_OPERATOR(remainder)
DEFINE_BINARY_OPERATOR(fmax)
DEFINE_BINARY_OPERATOR(fmin)
DEFINE_BINARY_OPERATOR(fdim)
DEFINE_BINARY_OPERATOR(pow)
DEFINE_BINARY_OPERATOR(hypot)
DEFINE_BINARY_OPERATOR(atan2)
DEFINE_TERNARY_OPERATOR(fma)
#undef DEFINE_TERNARY_OPERATOR
#undef DEFINE_TERNARY_OPERATOR_MMM
#undef DEFINE_TERNARY_OPERATOR_MMT
#undef DEFINE_TERNARY_OPERATOR_MTM
#undef DEFINE_TERNARY_OPERATOR_TMM
#undef DEFINE_TERNARY_OPERATOR_TTM
#undef DEFINE_TERNARY_OPERATOR_TMT
#undef DEFINE_TERNARY_OPERATOR_MTT
#undef DEFINE_BINARY_OPERATOR
#undef DEFINE_UNARY_OPERATOR
#undef DEFINE_UNARY_BOOL_OPERATOR
#undef DEFINE_OPERATOR
#undef DEFINE_BOOL_OPERATOR
}
#endif

View file

@ -1,40 +0,0 @@
/***************************************************************************
* Copyright (c) 2019, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
* Martin Renou *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XMASKED_VALUE_META_HPP
#define XTL_XMASKED_VALUE_META_HPP
#include <type_traits>
namespace xtl
{
template <class T, class B = bool>
class xmasked_value;
namespace detail
{
template <class E>
struct is_xmasked_value_impl : std::false_type
{
};
template <class T, class B>
struct is_xmasked_value_impl<xmasked_value<T, B>> : std::true_type
{
};
}
template <class E>
using is_xmasked_value = detail::is_xmasked_value_impl<E>;
template <class E, class R>
using disable_xmasked_value = std::enable_if_t<!is_xmasked_value<E>::value, R>;
}
#endif

View file

@ -1,549 +0,0 @@
/***************************************************************************
* Copyright (c) 2017, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XMETA_UTILS_HPP
#define XTL_XMETA_UTILS_HPP
#include <cstddef>
#include <type_traits>
#include "xfunctional.hpp"
#include "xtl_config.hpp"
namespace xtl
{
// TODO move to a xutils if we have one
// gcc 4.9 is affected by C++14 defect CGW 1558
// see http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
template <class... T>
struct make_void
{
using type = void;
};
template <class... T>
using void_t = typename make_void<T...>::type;
namespace mpl
{
/*************
* mpl types *
*************/
template <class... T>
struct vector
{
};
template <bool B>
using bool_ = std::integral_constant<bool, B>;
template <std::size_t S>
using size_t_ = std::integral_constant<std::size_t, S>;
/*******
* if_ *
*******/
template <bool B, class T, class F>
struct if_c : std::conditional<B, T, F>
{
};
template <bool B, class T, class F>
using if_c_t = typename if_c<B, T, F>::type;
template <class B, class T, class F>
struct if_ : if_c<B::value, T, F>
{
};
template <class B, class T, class F>
using if_t = typename if_<B, T, F>::type;
/***********
* eval_if *
***********/
template <bool B, class T, class F>
struct eval_if_c
{
using type = typename T::type;
};
template <class T, class F>
struct eval_if_c<false, T, F>
{
using type = typename F::type;
};
template <class B, class T, class F>
struct eval_if : eval_if_c<B::value, T, F>
{
};
template <class B, class T, class F>
using eval_if_t = typename eval_if<B, T, F>::type;
/********
* cast *
********/
namespace detail
{
template <class A, template <class...> class B>
struct cast_impl;
template <template <class...> class A, class... T, template <class...> class B>
struct cast_impl<A<T...>, B>
{
using type = B<T...>;
};
}
template <class A, template <class...> class B>
struct cast : detail::cast_impl<A, B>
{
};
template <class A, template <class...> class B>
using cast_t = typename cast<A, B>::type;
/********
* size *
********/
namespace detail
{
template <class L>
struct size_impl;
template <template <class...> class F, class... T>
struct size_impl<F<T...>> : size_t_<sizeof...(T)>
{
};
}
template <class L>
struct size : detail::size_impl<L>
{
};
/*********
* empty *
*********/
namespace detail
{
template <class L>
struct empty_impl;
template <template <class...> class F, class... T>
struct empty_impl<F<T...>> : bool_<sizeof...(T) == std::size_t(0)>
{
};
}
template <class L>
struct empty : detail::empty_impl<L>
{
};
template <class L>
using empty_t = typename empty<L>::type;
/********
* plus *
********/
namespace detail
{
template <class... T>
struct plus_impl;
template <>
struct plus_impl<> : size_t_<0>
{
};
template <class T1, class... T>
struct plus_impl<T1, T...> : size_t_<T1::value + plus_impl<T...>::value>
{
};
}
template <class... T>
struct plus : detail::plus_impl<T...>
{
};
/*********
* count *
*********/
namespace detail
{
template <class L, class V>
struct count_impl;
template <template <class...> class L, class... T, class V>
struct count_impl<L<T...>, V> : plus<std::is_same<T, V>...>
{
};
}
template <class L, class V>
struct count : detail::count_impl<L, V>
{
};
/************
* count_if *
************/
namespace detail
{
template <class L, template <class> class P>
struct count_if_impl;
template <template <class...> class L, class... T, template <class> class P>
struct count_if_impl<L<T...>, P> : plus<P<T>...>
{
};
}
template <class L, template <class> class P>
struct count_if : detail::count_if_impl<L, P>
{
};
/************
* contains *
************/
template <class L, class V>
using contains = bool_<count<L, V>::value != 0>;
/*********
* front *
*********/
namespace detail
{
template <class L>
struct front_impl;
template <template <class...> class L, class T, class... U>
struct front_impl<L<T, U...>>
{
using type = T;
};
}
template <class L>
struct front : detail::front_impl<L>
{
};
template <class L>
using front_t = typename front<L>::type;
/********
* back *
********/
namespace detail
{
template <class L>
struct back_impl;
template <template <class...> class L, class T>
struct back_impl<L<T>>
{
using type = T;
};
// Compilation time improvement
template <template <class...> class L, class T1, class T2>
struct back_impl<L<T1, T2>>
{
using type = T2;
};
template <template <class...> class L, class T1, class T2, class T3>
struct back_impl<L<T1, T2, T3>>
{
using type = T3;
};
template <template <class...> class L, class T1, class T2, class T3, class T4>
struct back_impl<L<T1, T2, T3, T4>>
{
using type = T4;
};
template <template <class...> class L, class T, class... U>
struct back_impl<L<T, U...>> : back_impl<L<U...>>
{
};
}
template <class L>
struct back : detail::back_impl<L>
{
};
template <class L>
using back_t = typename back<L>::type;
/**************
* push_front *
**************/
namespace detail
{
template <class L, class... T>
struct push_front_impl;
template <template <class...> class L, class... U, class... T>
struct push_front_impl<L<U...>, T...>
{
using type = L<T..., U...>;
};
}
template <class L, class... T>
struct push_front : detail::push_front_impl<L, T...>
{
};
template <class L, class... T>
using push_front_t = typename push_front<L, T...>::type;
/*************
* push_back *
*************/
namespace detail
{
template <class L, class... T>
struct push_back_impl;
template <template <class...> class L, class... U, class... T>
struct push_back_impl<L<U...>, T...>
{
using type = L<U..., T...>;
};
}
template <class L, class... T>
struct push_back : detail::push_back_impl<L, T...>
{
};
template <class L, class... T>
using push_back_t = typename push_back<L, T...>::type;
/*************
* pop_front *
*************/
namespace detail
{
template <class L>
struct pop_front_impl;
template <template <class...> class L, class T, class... U>
struct pop_front_impl<L<T, U...>>
{
using type = L<U...>;
};
}
template <class L>
struct pop_front : detail::pop_front_impl<L>
{
};
template <class L>
using pop_front_t = typename pop_front<L>::type;
/*************
* transform *
*************/
namespace detail
{
template <template <class...> class F, class L>
struct transform_impl;
template <template <class...> class F, template <class...> class L, class... T>
struct transform_impl<F, L<T...>>
{
using type = L<F<T>...>;
};
}
template <template <class...> class F, class L>
struct transform : detail::transform_impl<F, L>
{
};
template <template <class...> class F, class L>
using transform_t = typename transform<F, L>::type;
/*************
* merge_set *
*************/
namespace detail
{
template <class S1, class S2>
struct merge_set_impl;
template <template <class...> class L, class... T>
struct merge_set_impl<L<T...>, L<>>
{
using type = L<T...>;
};
template <template <class...> class L, class... T, class U1, class... U>
struct merge_set_impl<L<T...>, L<U1, U...>>
{
using type = typename merge_set_impl<if_t<contains<L<T...>, U1>,
L<T...>,
L<T..., U1>>,
L<U...>>::type;
};
}
template <class S1, class S2>
struct merge_set : detail::merge_set_impl<S1, S2>
{
};
template <class S1, class S2>
using merge_set_t = typename merge_set<S1, S2>::type;
/***********
* find_if *
***********/
template <template <class> class Test, class L>
struct find_if;
namespace detail
{
template <template <class> class Test, std::size_t I, class... T>
struct find_if_impl;
template <template <class> class Test, std::size_t I>
struct find_if_impl<Test, I> : size_t_<I>
{
};
template <template <class> class Test, std::size_t I, class T0, class... T>
struct find_if_impl<Test, I, T0, T...> : std::conditional_t<Test<T0>::value,
size_t_<I>,
find_if_impl<Test, I + 1, T...>>
{
};
}
template <template <class> class Test, template <class...> class L, class... T>
struct find_if<Test, L<T...>> : detail::find_if_impl<Test, 0, T...>
{
};
/*********
* split *
*********/
namespace detail
{
template <std::size_t N, class L1, class L2>
struct transfer
{
using new_l1 = push_back_t<L1, front_t<L2>>;
using new_l2 = pop_front_t<L2>;
using new_transfer = transfer<N - 1, new_l1, new_l2>;
using first_type = typename new_transfer::first_type;
using second_type = typename new_transfer::second_type;
};
template <class L1, class L2>
struct transfer<0, L1, L2>
{
using first_type = L1;
using second_type = L2;
};
template <std::size_t N, class L>
struct split_impl
{
using tr_type = transfer<N, vector<>, L>;
using first_type = typename tr_type::first_type;
using second_type = typename tr_type::second_type;
};
}
template <std::size_t N, class L>
struct split : detail::split_impl<N, L>
{
};
/**********
* unique *
**********/
namespace detail
{
template <class L>
struct unique_impl;
template <template <class...> class L, class... T>
struct unique_impl<L<T...>>
{
using type = merge_set_t<L<>, L<T...>>;
};
}
template <class L>
struct unique : detail::unique_impl<L>
{
};
template <class L>
using unique_t = typename unique<L>::type;
/*************
* static_if *
*************/
template <class TF, class FF>
decltype(auto) static_if(std::true_type, const TF& tf, const FF&)
{
return tf(identity());
}
template <class TF, class FF>
decltype(auto) static_if(std::false_type, const TF&, const FF& ff)
{
return ff(identity());
}
template <bool cond, class TF, class FF>
decltype(auto) static_if(const TF& tf, const FF& ff)
{
return static_if(std::integral_constant<bool, cond>(), tf, ff);
}
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,140 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
* Martin Renou *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_OPTIONAL_META_HPP
#define XTL_OPTIONAL_META_HPP
#include <type_traits>
#include "xmasked_value_meta.hpp"
#include "xmeta_utils.hpp"
#include "xtype_traits.hpp"
namespace xtl
{
template <class CT, class CB = bool>
class xoptional;
namespace detail
{
template <class E>
struct is_xoptional_impl : std::false_type
{
};
template <class CT, class CB>
struct is_xoptional_impl<xoptional<CT, CB>> : std::true_type
{
};
template <class CT, class CTO, class CBO>
using converts_from_xoptional = disjunction<
std::is_constructible<CT, const xoptional<CTO, CBO>&>,
std::is_constructible<CT, xoptional<CTO, CBO>&>,
std::is_constructible<CT, const xoptional<CTO, CBO>&&>,
std::is_constructible<CT, xoptional<CTO, CBO>&&>,
std::is_convertible<const xoptional<CTO, CBO>&, CT>,
std::is_convertible<xoptional<CTO, CBO>&, CT>,
std::is_convertible<const xoptional<CTO, CBO>&&, CT>,
std::is_convertible<xoptional<CTO, CBO>&&, CT>
>;
template <class CT, class CTO, class CBO>
using assigns_from_xoptional = disjunction<
std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&>,
std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&>,
std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&&>,
std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&&>
>;
template <class... Args>
struct common_optional_impl;
template <class T>
struct common_optional_impl<T>
{
using type = std::conditional_t<is_xoptional_impl<T>::value, T, xoptional<T>>;
};
template <class T>
struct identity
{
using type = T;
};
template <class T>
struct get_value_type
{
using type = typename T::value_type;
};
template<class T1, class T2>
struct common_optional_impl<T1, T2>
{
using decay_t1 = std::decay_t<T1>;
using decay_t2 = std::decay_t<T2>;
using type1 = xtl::mpl::eval_if_t<std::is_fundamental<decay_t1>, identity<decay_t1>, get_value_type<decay_t1>>;
using type2 = xtl::mpl::eval_if_t<std::is_fundamental<decay_t2>, identity<decay_t2>, get_value_type<decay_t2>>;
using type = xoptional<std::common_type_t<type1, type2>>;
};
template <class T1, class T2, class B2>
struct common_optional_impl<T1, xoptional<T2, B2>>
: common_optional_impl<T1, T2>
{
};
template <class T1, class B1, class T2>
struct common_optional_impl<xoptional<T1, B1>, T2>
: common_optional_impl<T1, T2>
{
};
template <class T1, class B1, class T2, class B2>
struct common_optional_impl<xoptional<T1, B1>, xoptional<T2, B2>>
: common_optional_impl<T1, T2>
{
};
template <class T1, class T2, class... Args>
struct common_optional_impl<T1, T2, Args...>
{
using type = typename common_optional_impl<
typename common_optional_impl<T1, T2>::type,
Args...
>::type;
};
}
template <class E>
using is_xoptional = detail::is_xoptional_impl<E>;
template <class E, class R = void>
using disable_xoptional = std::enable_if_t<!is_xoptional<E>::value, R>;
template <class... Args>
struct at_least_one_xoptional : disjunction<is_xoptional<Args>...>
{
};
template <class... Args>
struct common_optional : detail::common_optional_impl<Args...>
{
};
template <class... Args>
using common_optional_t = typename common_optional<Args...>::type;
template <class E>
struct is_not_xoptional_nor_xmasked_value : negation<disjunction<is_xoptional<E>, is_xmasked_value<E>>>
{
};
}
#endif

View file

@ -1,621 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_OPTIONAL_SEQUENCE_HPP
#define XTL_OPTIONAL_SEQUENCE_HPP
#include <array>
#include <bitset>
#include <cstddef>
#include <iterator>
#include <memory>
#include <utility>
#include <vector>
#include "xdynamic_bitset.hpp"
#include "xiterator_base.hpp"
#include "xoptional.hpp"
#include "xsequence.hpp"
namespace xtl
{
/**************************************
* Optimized 1-D xoptional containers *
**************************************/
template <class ITV, class ITB>
class xoptional_iterator;
template <class BC, class FC>
class xoptional_sequence
{
public:
// Internal typedefs
using base_container_type = BC;
using base_value_type = typename base_container_type::value_type;
using base_reference = typename base_container_type::reference;
using base_const_reference = typename base_container_type::const_reference;
using flag_container_type = FC;
using flag_type = typename flag_container_type::value_type;
using flag_reference = typename flag_container_type::reference;
using flag_const_reference = typename flag_container_type::const_reference;
// Container typedefs
using value_type = xoptional<base_value_type, flag_type>;
using reference = xoptional<base_reference, flag_reference>;
using const_reference = xoptional<base_const_reference, flag_const_reference>;
using pointer = xclosure_pointer<reference>;
using const_pointer = xclosure_pointer<const_reference>;
// Other typedefs
using size_type = typename base_container_type::size_type;
using difference_type = typename base_container_type::difference_type;
using iterator = xoptional_iterator<typename base_container_type::iterator,
typename flag_container_type::iterator>;
using const_iterator = xoptional_iterator<typename base_container_type::const_iterator,
typename flag_container_type::const_iterator>;
using reverse_iterator = xoptional_iterator<typename base_container_type::reverse_iterator,
typename flag_container_type::reverse_iterator>;
using const_reverse_iterator = xoptional_iterator<typename base_container_type::const_reverse_iterator,
typename flag_container_type::const_reverse_iterator>;
bool empty() const noexcept;
size_type size() const noexcept;
size_type max_size() const noexcept;
reference at(size_type i);
const_reference at(size_type i) const;
reference operator[](size_type i);
const_reference operator[](size_type i) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
reverse_iterator rbegin() noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
base_container_type value() && noexcept;
base_container_type& value() & noexcept;
const base_container_type& value() const & noexcept;
flag_container_type has_value() && noexcept;
flag_container_type& has_value() & noexcept;
const flag_container_type& has_value() const & noexcept;
protected:
xoptional_sequence() = default;
xoptional_sequence(size_type s, const base_value_type& v);
template <class CTO, class CBO>
xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v);
~xoptional_sequence() = default;
xoptional_sequence(const xoptional_sequence&) = default;
xoptional_sequence& operator=(const xoptional_sequence&) = default;
xoptional_sequence(xoptional_sequence&&) = default;
xoptional_sequence& operator=(xoptional_sequence&&) = default;
base_container_type m_values;
flag_container_type m_flags;
};
template <class BC, class FC>
bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
template <class BC, class FC>
bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
template <class BC, class FC>
bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
template <class BC, class FC>
bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
template <class BC, class FC>
bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
template <class BC, class FC>
bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
/********************************
* xoptional_array declarations *
********************************/
// There is no value_type in std::bitset ...
template <class T, std::size_t I, class BC = xdynamic_bitset<std::size_t>>
class xoptional_array : public xoptional_sequence<std::array<T, I>, BC>
{
public:
using self_type = xoptional_array;
using base_container_type = std::array<T, I>;
using flag_container_type = BC;
using base_type = xoptional_sequence<base_container_type, flag_container_type>;
using base_value_type = typename base_type::base_value_type;
using size_type = typename base_type::size_type;
xoptional_array() = default;
xoptional_array(size_type s, const base_value_type& v);
template <class CTO, class CBO>
xoptional_array(size_type s, const xoptional<CTO, CBO>& v);
};
/********************
* xoptional_vector *
********************/
template <class T, class A = std::allocator<T>, class BC = xdynamic_bitset<std::size_t>>
class xoptional_vector : public xoptional_sequence<std::vector<T, A>, BC>
{
public:
using self_type = xoptional_vector;
using base_container_type = std::vector<T, A>;
using flag_container_type = BC;
using base_type = xoptional_sequence<base_container_type, flag_container_type>;
using base_value_type = typename base_type::base_value_type;
using allocator_type = A;
using value_type = typename base_type::value_type;
using size_type = typename base_type::size_type;
using difference_type = typename base_type::difference_type;
using reference = typename base_type::reference;
using const_reference = typename base_type::const_reference;
using pointer = typename base_type::pointer;
using const_pointer = typename base_type::const_pointer;
using iterator = typename base_type::iterator;
using const_iterator = typename base_type::const_iterator;
using reverse_iterator = typename base_type::reverse_iterator;
using const_reverse_iterator = typename base_type::const_reverse_iterator;
xoptional_vector() = default;
xoptional_vector(size_type, const base_value_type&);
template <class CTO, class CBO>
xoptional_vector(size_type, const xoptional<CTO, CBO>&);
void resize(size_type);
void resize(size_type, const base_value_type&);
template <class CTO, class CBO>
void resize(size_type, const xoptional<CTO, CBO>&);
};
/**********************************
* xoptional_iterator declaration *
**********************************/
template <class ITV, class ITB>
struct xoptional_iterator_traits
{
using iterator_type = xoptional_iterator<ITV, ITB>;
using value_type = xoptional<typename ITV::value_type, typename ITB::value_type>;
using reference = xoptional<typename ITV::reference, typename ITB::reference>;
using pointer = xclosure_pointer<reference>;
using difference_type = typename ITV::difference_type;
};
template <class ITV, class ITB>
class xoptional_iterator : public xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>
{
public:
using self_type = xoptional_iterator<ITV, ITB>;
using base_type = xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>;
using value_type = typename base_type::value_type;
using reference = typename base_type::reference;
using pointer = typename base_type::pointer;
using difference_type = typename base_type::difference_type;
xoptional_iterator() = default;
xoptional_iterator(ITV itv, ITB itb);
self_type& operator++();
self_type& operator--();
self_type& operator+=(difference_type n);
self_type& operator-=(difference_type n);
difference_type operator-(const self_type& rhs) const;
reference operator*() const;
pointer operator->() const;
bool operator==(const self_type& rhs) const;
bool operator<(const self_type& rhs) const;
private:
ITV m_itv;
ITB m_itb;
};
/*************************************
* xoptional_sequence implementation *
*************************************/
template <class BC, class FC>
inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const base_value_type& v)
: m_values(make_sequence<base_container_type>(s, v)),
m_flags(make_sequence<flag_container_type>(s, true))
{
}
template <class BC, class FC>
template <class CTO, class CBO>
inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v)
: m_values(make_sequence<base_container_type>(s, v.value())), m_flags(make_sequence<flag_container_type>(s, v.has_value()))
{
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::empty() const noexcept -> bool
{
return m_values.empty();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::size() const noexcept -> size_type
{
return m_values.size();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::max_size() const noexcept -> size_type
{
return m_values.max_size();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::at(size_type i) -> reference
{
return reference(m_values.at(i), m_flags.at(i));
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::at(size_type i) const -> const_reference
{
return const_reference(m_values.at(i), m_flags.at(i));
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::operator[](size_type i) -> reference
{
return reference(m_values[i], m_flags[i]);
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::operator[](size_type i) const -> const_reference
{
return const_reference(m_values[i], m_flags[i]);
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::front() -> reference
{
return reference(m_values.front(), m_flags.front());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::front() const -> const_reference
{
return const_reference(m_values.front(), m_flags.front());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::back() -> reference
{
return reference(m_values.back(), m_flags.back());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::back() const -> const_reference
{
return const_reference(m_values.back(), m_flags.back());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::begin() noexcept -> iterator
{
return iterator(m_values.begin(), m_flags.begin());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::end() noexcept -> iterator
{
return iterator(m_values.end(), m_flags.end());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::begin() const noexcept -> const_iterator
{
return cbegin();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::end() const noexcept -> const_iterator
{
return cend();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::cbegin() const noexcept -> const_iterator
{
return const_iterator(m_values.cbegin(), m_flags.cbegin());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::cend() const noexcept -> const_iterator
{
return const_iterator(m_values.cend(), m_flags.cend());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::rbegin() noexcept -> reverse_iterator
{
return reverse_iterator(m_values.rbegin(), m_flags.rbegin());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::rend() noexcept -> reverse_iterator
{
return reverse_iterator(m_values.rend(), m_flags.rend());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::rbegin() const noexcept -> const_reverse_iterator
{
return crbegin();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::rend() const noexcept -> const_reverse_iterator
{
return crend();
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::crbegin() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(m_values.crbegin(), m_flags.crbegin());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::crend() const noexcept -> const_reverse_iterator
{
return const_reverse_iterator(m_values.crend(), m_flags.crend());
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::value() && noexcept -> base_container_type
{
return m_values;
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::value() & noexcept -> base_container_type&
{
return m_values;
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::value() const & noexcept -> const base_container_type&
{
return m_values;
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::has_value() && noexcept-> flag_container_type
{
return m_flags;
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::has_value() & noexcept -> flag_container_type&
{
return m_flags;
}
template <class BC, class FC>
inline auto xoptional_sequence<BC, FC>::has_value() const & noexcept -> const flag_container_type&
{
return m_flags;
}
template <class BC, class FC>
inline bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return lhs.value() == rhs.value() && lhs.has_value() == rhs.has_value();
}
template <class BC, class FC>
inline bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return !(lhs == rhs);
}
template <class BC, class FC>
inline bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return lhs.value() < rhs.value() && lhs.has_value() == rhs.has_value();
}
template <class BC, class FC>
inline bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return lhs.value() <= rhs.value() && lhs.has_value() == rhs.has_value();
}
template <class BC, class FC>
inline bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return lhs.value() > rhs.value() && lhs.has_value() == rhs.has_value();
}
template <class BC, class FC>
inline bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
{
return lhs.value() >= rhs.value() && lhs.has_value() == rhs.has_value();
}
/**********************************
* xoptional_array implementation *
**********************************/
template <class T, std::size_t I, class BC>
xoptional_array<T, I, BC>::xoptional_array(size_type s, const base_value_type& v)
: base_type(s, v)
{
}
template <class T, std::size_t I, class BC>
template <class CTO, class CBO>
xoptional_array<T, I, BC>::xoptional_array(size_type s, const xoptional<CTO, CBO>& v)
: base_type(s, v)
{
}
/*******************************************************
* xoptional_array and xoptional_vector implementation *
*******************************************************/
template <class T, class A, class BC>
xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const base_value_type& v)
: base_type(s, v)
{
}
template <class T, class A, class BC>
template <class CTO, class CBO>
xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const xoptional<CTO, CBO>& v)
: base_type(s, v)
{
}
template <class T, class A, class BC>
void xoptional_vector<T, A, BC>::resize(size_type s)
{
// Default to missing
this->m_values.resize(s);
this->m_flags.resize(s, false);
}
template <class T, class A, class BC>
void xoptional_vector<T, A, BC>::resize(size_type s, const base_value_type& v)
{
this->m_values.resize(s, v);
this->m_flags.resize(s, true);
}
template <class T, class A, class BC>
template <class CTO, class CBO>
void xoptional_vector<T, A, BC>::resize(size_type s, const xoptional<CTO, CBO>& v)
{
this->m_values.resize(s, v.value());
this->m_flags.resize(s, v.has_value());
}
/*************************************
* xoptional_iterator implementation *
*************************************/
template <class ITV, class ITB>
xoptional_iterator<ITV, ITB>::xoptional_iterator(ITV itv, ITB itb)
: m_itv(itv), m_itb(itb)
{
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator++() -> self_type&
{
++m_itv;
++m_itb;
return *this;
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator--() -> self_type&
{
--m_itv;
--m_itb;
return *this;
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator+=(difference_type n) -> self_type&
{
m_itv += n;
m_itb += n;
return *this;
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator-=(difference_type n) -> self_type&
{
m_itv -= n;
m_itb -= n;
return *this;
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator-(const self_type& rhs) const -> difference_type
{
return m_itv - rhs.m_itv;
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator*() const -> reference
{
return reference(*m_itv, *m_itb);
}
template <class ITV, class ITB>
auto xoptional_iterator<ITV, ITB>::operator-> () const -> pointer
{
return pointer(operator*());
}
template <class ITV, class ITB>
bool xoptional_iterator<ITV, ITB>::operator==(const self_type& rhs) const
{
return m_itv == rhs.m_itv && m_itb == rhs.m_itb;
}
template <class ITV, class ITB>
bool xoptional_iterator<ITV, ITB>::operator<(const self_type& rhs) const
{
return m_itv < rhs.m_itv && m_itb < rhs.m_itb;
}
}
#endif

View file

@ -1,48 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XPROXY_WRAPPER_HPP
#define XTL_XPROXY_WRAPPER_HPP
#include "xclosure.hpp"
namespace xtl
{
template <class P>
class xproxy_wrapper_impl : public P
{
public:
using self_type = xproxy_wrapper_impl<P>;
using lv_pointer = xclosure_pointer<P&>;
using rv_pointer = xclosure_pointer<P>;
explicit xproxy_wrapper_impl(P&& rhs)
: P(std::move(rhs))
{
}
inline lv_pointer operator&() & { return lv_pointer(*this); }
inline rv_pointer operator&() && { return rv_pointer(std::move(*this)); }
};
template <class P>
using xproxy_wrapper = std::conditional_t<std::is_class<P>::value,
xproxy_wrapper_impl<P>,
xclosure_wrapper<P>>;
template <class P>
inline xproxy_wrapper<P> proxy_wrapper(P&& proxy)
{
return xproxy_wrapper<P>(std::forward<P>(proxy));
}
}
#endif

View file

@ -1,203 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_SEQUENCE_HPP
#define XTL_SEQUENCE_HPP
#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>
#include <vector>
#include "xtl_config.hpp"
#include "xmeta_utils.hpp"
namespace xtl
{
template <class S>
S make_sequence(typename S::size_type size);
template <class S>
S make_sequence(typename S::size_type size, typename S::value_type v);
template <class S>
S make_sequence(std::initializer_list<typename S::value_type> init);
template <class R, class A>
decltype(auto) forward_sequence(A&& s);
// equivalent to std::size(c) in c++17
template <class C>
constexpr auto sequence_size(const C& c) -> decltype(c.size());
// equivalent to std::size(a) in c++17
template <class T, std::size_t N>
constexpr std::size_t sequence_size(const T (&a)[N]);
/********************************
* make_sequence implementation *
********************************/
namespace detail
{
template <class S>
struct sequence_builder
{
using value_type = typename S::value_type;
using size_type = typename S::size_type;
inline static S make(size_type size)
{
return S(size);
}
inline static S make(size_type size, value_type v)
{
return S(size, v);
}
inline static S make(std::initializer_list<value_type> init)
{
return S(init);
}
};
template <class T, std::size_t N>
struct sequence_builder<std::array<T, N>>
{
using sequence_type = std::array<T, N>;
using value_type = typename sequence_type::value_type;
using size_type = typename sequence_type::size_type;
inline static sequence_type make(size_type /*size*/)
{
return sequence_type();
}
inline static sequence_type make(size_type /*size*/, value_type v)
{
sequence_type s;
s.fill(v);
return s;
}
inline static sequence_type make(std::initializer_list<value_type> init)
{
sequence_type s;
std::copy(init.begin(), init.end(), s.begin());
return s;
}
};
}
template <class S>
inline S make_sequence(typename S::size_type size)
{
return detail::sequence_builder<S>::make(size);
}
template <class S>
inline S make_sequence(typename S::size_type size, typename S::value_type v)
{
return detail::sequence_builder<S>::make(size, v);
}
template <class S>
inline S make_sequence(std::initializer_list<typename S::value_type> init)
{
return detail::sequence_builder<S>::make(init);
}
/***********************************
* forward_sequence implementation *
***********************************/
namespace detail
{
template <class R, class A, class E = void>
struct sequence_forwarder_impl
{
template <class T>
static inline R forward(const T& r)
{
R ret;
std::copy(std::begin(r), std::end(r), std::begin(ret));
return ret;
}
};
template <class R, class A>
struct sequence_forwarder_impl<R, A, void_t<decltype(std::declval<R>().resize(std::size_t()))>>
{
template <class T>
static inline auto forward(const T& r)
{
return R(std::begin(r), std::end(r));
}
};
template <class R, class A>
struct sequence_forwarder
: sequence_forwarder_impl<R, A>
{
};
template <class R>
struct sequence_forwarder<R, R>
{
template <class T>
static inline T&& forward(T&& t) noexcept
{
return std::forward<T>(t);
}
};
template <class R, class A>
using forwarder_type = detail::sequence_forwarder<
std::decay_t<R>,
std::remove_cv_t<std::remove_reference_t<A>>
>;
}
template <class R, class A>
inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type& s)
{
using forwarder = detail::forwarder_type<R, A>;
return forwarder::forward(std::forward<A>(s));
}
template <class R, class A>
inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type&& s)
{
using forwarder = detail::forwarder_type<R, A>;
static_assert(!std::is_lvalue_reference<A>::value,
"Can not forward an rvalue as an lvalue.");
return forwarder::forward(std::move(s));
}
/********************************
* sequence_size implementation *
********************************/
// equivalent to std::size(c) in c++17
template <class C>
constexpr auto sequence_size(const C& c) -> decltype(c.size())
{
return c.size();
}
// equivalent to std::size(a) in c++17
template <class T, std::size_t N>
constexpr std::size_t sequence_size(const T (&)[N])
{
return N;
}
}
#endif

View file

@ -1,20 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XSPAN_HPP
#define XTL_XSPAN_HPP
#include "xspan_impl.hpp"
namespace xtl
{
using tcb::span;
constexpr std::ptrdiff_t dynamic_extent = tcb::dynamic_extent;
}
#endif

View file

@ -1,778 +0,0 @@
// https://github.com/tcbrindle/span/blob/master/include/tcb/span.hpp
// TCP SPAN @commit cd0c6d0
/*
This is an implementation of std::span from P0122R7
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0122r7.pdf
*/
// Copyright Tristan Brindle 2018.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file ../../LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
#ifndef TCB_SPAN_HPP_INCLUDED
#define TCB_SPAN_HPP_INCLUDED
#include <array>
#include <cstddef>
#include <type_traits>
#ifndef TCB_SPAN_NO_EXCEPTIONS
// Attempt to discover whether we're being compiled with exception support
#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
#define TCB_SPAN_NO_EXCEPTIONS
#endif
#endif
#ifndef TCB_SPAN_NO_EXCEPTIONS
#include <cstdio>
#include <stdexcept>
#endif
// Various feature test macros
#ifndef TCB_SPAN_NAMESPACE_NAME
#define TCB_SPAN_NAMESPACE_NAME tcb
#endif
#ifdef TCB_SPAN_STD_COMPLIANT_MODE
#define TCB_SPAN_NO_DEPRECATION_WARNINGS
#endif
#ifndef TCB_SPAN_NO_DEPRECATION_WARNINGS
#define TCB_SPAN_DEPRECATED_FOR(msg) [[deprecated(msg)]]
#else
#define TCB_SPAN_DEPRECATED_FOR(msg)
#endif
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#define TCB_SPAN_HAVE_CPP17
#endif
#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
#define TCB_SPAN_HAVE_CPP14
#endif
namespace TCB_SPAN_NAMESPACE_NAME {
// Establish default contract checking behavior
#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
!defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
!defined(TCB_SPAN_NO_CONTRACT_CHECKING)
#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
#define TCB_SPAN_NO_CONTRACT_CHECKING
#else
#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
#endif
#endif
#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
struct contract_violation_error : std::logic_error {
explicit contract_violation_error(const char* msg) : std::logic_error(msg)
{}
};
inline void contract_violation(const char* msg)
{
throw contract_violation_error(msg);
}
#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
[[noreturn]] inline void contract_violation(const char* /*unused*/)
{
std::terminate();
}
#endif
#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
#define TCB_SPAN_STRINGIFY(cond) #cond
#define TCB_SPAN_EXPECT(cond) \
cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
#else
#define TCB_SPAN_EXPECT(cond)
#endif
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
#define TCB_SPAN_INLINE_VAR inline
#else
#define TCB_SPAN_INLINE_VAR
#endif
#if defined(TCB_SPAN_HAVE_CPP14) || \
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
#define TCB_SPAN_CONSTEXPR14 constexpr
#else
#define TCB_SPAN_CONSTEXPR14
#endif
#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
#define TCB_SPAN_CONSTEXPR11 constexpr
#else
#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
#endif
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
#endif
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
#define TCB_SPAN_HAVE_STD_BYTE
#endif
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
#endif
#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
#else
#define TCB_SPAN_ARRAY_CONSTEXPR
#endif
#ifdef TCB_SPAN_HAVE_STD_BYTE
using byte = std::byte;
#else
using byte = unsigned char;
#endif
TCB_SPAN_INLINE_VAR constexpr std::ptrdiff_t dynamic_extent = -1;
template <typename ElementType, std::ptrdiff_t Extent = dynamic_extent>
class span;
namespace detail {
template <typename E, std::ptrdiff_t S>
struct span_storage {
constexpr span_storage() noexcept = default;
constexpr span_storage(E* ptr, std::ptrdiff_t /*unused*/) noexcept
: ptr(ptr)
{}
E* ptr = nullptr;
static constexpr std::ptrdiff_t size = S;
};
template <typename E>
struct span_storage<E, dynamic_extent> {
constexpr span_storage() noexcept = default;
constexpr span_storage(E* ptr, std::size_t size) noexcept
: ptr(ptr), size(size)
{}
E* ptr = nullptr;
std::size_t size = 0;
};
// Reimplementation of C++17 std::size() and std::data()
#if defined(TCB_SPAN_HAVE_CPP17) || \
defined(__cpp_lib_nonmember_container_access)
using std::data;
using std::size;
#else
template <class C>
constexpr auto size(const C& c) -> decltype(c.size())
{
return c.size();
}
template <class T, std::size_t N>
constexpr std::size_t size(const T (&)[N]) noexcept
{
return N;
}
template <class C>
constexpr auto data(C& c) -> decltype(c.data())
{
return c.data();
}
template <class C>
constexpr auto data(const C& c) -> decltype(c.data())
{
return c.data();
}
template <class T, std::size_t N>
constexpr T* data(T (&array)[N]) noexcept
{
return array;
}
template <class E>
constexpr const E* data(std::initializer_list<E> il) noexcept
{
return il.begin();
}
#endif // TCB_SPAN_HAVE_CPP17
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
using std::void_t;
#else
template <typename...>
using void_t = void;
#endif
template <typename T>
using uncvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template <typename>
struct is_span : std::false_type {};
template <typename T, std::ptrdiff_t S>
struct is_span<span<T, S>> : std::true_type {};
template <typename>
struct is_std_array : std::false_type {};
template <typename T, std::size_t N>
struct is_std_array<std::array<T, N>> : std::true_type {};
template <typename, typename = void>
struct has_size_and_data : std::false_type {};
template <typename T>
struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
decltype(detail::data(std::declval<T>()))>>
: std::true_type {};
template <typename C, typename U = uncvref_t<C>>
struct is_container {
static constexpr bool value =
!is_span<U>::value && !is_std_array<U>::value &&
!std::is_array<U>::value && has_size_and_data<C>::value;
};
template <typename T>
using remove_pointer_t = typename std::remove_pointer<T>::type;
template <typename, typename, typename = void>
struct is_container_element_type_compatible : std::false_type {};
template <typename T, typename E>
struct is_container_element_type_compatible<
T, E, void_t<decltype(detail::data(std::declval<T>()))>>
: std::is_convertible<
remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
E (*)[]> {};
template <typename, typename = size_t>
struct is_complete : std::false_type {};
template <typename T>
struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
} // namespace detail
template <typename ElementType, std::ptrdiff_t Extent>
class span {
static_assert(Extent == dynamic_extent || Extent >= 0,
"A span must have an extent greater than or equal to zero, "
"or a dynamic extent");
static_assert(std::is_object<ElementType>::value,
"A span's ElementType must be an object type (not a "
"reference type or void)");
static_assert(detail::is_complete<ElementType>::value,
"A span's ElementType must be a complete type (not a forward "
"declaration)");
static_assert(!std::is_abstract<ElementType>::value,
"A span's ElementType cannot be an abstract class type");
using storage_type = detail::span_storage<ElementType, Extent>;
public:
// constants and types
using element_type = ElementType;
using value_type = typename std::remove_cv<ElementType>::type;
using index_type = std::size_t;
using difference_type = std::ptrdiff_t;
using pointer = ElementType*;
using reference = ElementType&;
using iterator = pointer;
using const_iterator = const ElementType*;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
static constexpr index_type extent = static_cast<index_type>(Extent);
// [span.cons], span constructors, copy, assignment, and destructor
template <std::ptrdiff_t E = Extent,
typename std::enable_if<E <= 0, int>::type = 0>
constexpr span() noexcept
{}
TCB_SPAN_CONSTEXPR11 span(pointer ptr, index_type count)
: storage_(ptr, count)
{
TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
}
TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
: storage_(first_elem, last_elem - first_elem)
{
TCB_SPAN_EXPECT(extent == dynamic_extent ||
last_elem - first_elem == extent);
}
template <
std::size_t N, std::ptrdiff_t E = Extent,
typename std::enable_if<
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
detail::is_container_element_type_compatible<
element_type (&)[N], ElementType>::value,
int>::type = 0>
constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
{}
template <
std::size_t N, std::ptrdiff_t E = Extent,
typename std::enable_if<
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
detail::is_container_element_type_compatible<
std::array<value_type, N>&, ElementType>::value,
int>::type = 0>
TCB_SPAN_ARRAY_CONSTEXPR span(std::array<value_type, N>& arr) noexcept
: storage_(arr.data(), N)
{}
template <
std::size_t N, std::ptrdiff_t E = Extent,
typename std::enable_if<
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
detail::is_container_element_type_compatible<
const std::array<value_type, N>&, ElementType>::value,
int>::type = 0>
TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<value_type, N>& arr) noexcept
: storage_(arr.data(), N)
{}
template <typename Container,
typename std::enable_if<
detail::is_container<Container>::value &&
detail::is_container_element_type_compatible<
Container&, ElementType>::value,
int>::type = 0>
TCB_SPAN_CONSTEXPR11 span(Container& cont)
: storage_(detail::data(cont), detail::size(cont))
{
TCB_SPAN_EXPECT(extent == dynamic_extent ||
static_cast<std::ptrdiff_t>(detail::size(cont)) ==
extent);
}
template <typename Container,
typename std::enable_if<
detail::is_container<Container>::value &&
detail::is_container_element_type_compatible<
const Container&, ElementType>::value,
int>::type = 0>
TCB_SPAN_CONSTEXPR11 span(const Container& cont)
: storage_(detail::data(cont), detail::size(cont))
{
TCB_SPAN_EXPECT(extent == dynamic_extent ||
static_cast<std::ptrdiff_t>(detail::size(cont)) ==
extent);
}
constexpr span(const span& other) noexcept = default;
template <typename OtherElementType, std::ptrdiff_t OtherExtent,
typename std::enable_if<
(Extent == OtherExtent || Extent == dynamic_extent) &&
std::is_convertible<OtherElementType (*)[],
ElementType (*)[]>::value,
int>::type = 0>
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
: storage_(other.data(), other.size())
{}
~span() noexcept = default;
span& operator=(const span& other) noexcept = default;
// [span.sub], span subviews
template <std::ptrdiff_t Count>
TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const
{
TCB_SPAN_EXPECT(Count >= 0 && Count <= size());
return {data(), Count};
}
template <std::ptrdiff_t Count>
TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const
{
TCB_SPAN_EXPECT(Count >= 0 && Count <= size());
return {data() + (size() - Count), Count};
}
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
using subspan_return_t =
span<ElementType, Count != dynamic_extent
? Count
: (Extent != dynamic_extent ? Extent - Offset
: dynamic_extent)>;
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
{
TCB_SPAN_EXPECT((Offset >= 0 && Offset <= size()) &&
(Count == dynamic_extent ||
(Count >= 0 && Offset + Count <= size())));
return {data() + Offset,
Count != dynamic_extent
? Count
: (Extent != dynamic_extent ? Extent - Offset
: size() - Offset)};
}
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
first(index_type count) const
{
TCB_SPAN_EXPECT(count >= 0 && count <= size());
return {data(), count};
}
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
last(index_type count) const
{
TCB_SPAN_EXPECT(count >= 0 && count <= size());
return {data() + (size() - count), count};
}
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
subspan(index_type offset, index_type count = static_cast<index_type>(dynamic_extent)) const
{
TCB_SPAN_EXPECT((offset >= 0 && offset <= size()) &&
(count == dynamic_extent ||
(count >= 0 && offset + count <= size())));
return {data() + offset,
count == dynamic_extent ? size() - offset : count};
}
// [span.obs], span observers
constexpr index_type size() const noexcept { return storage_.size; }
constexpr index_type size_bytes() const noexcept
{
return size() * sizeof(element_type);
}
constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access
TCB_SPAN_CONSTEXPR11 reference operator[](index_type idx) const
{
TCB_SPAN_EXPECT(idx >= 0 && idx < size());
return *(data() + idx);
}
/* Extension: not in P0122 */
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
TCB_SPAN_CONSTEXPR14 reference at(index_type idx) const
{
#ifndef TCB_SPAN_NO_EXCEPTIONS
if (idx < 0 || idx >= size()) {
char msgbuf[64] = {
0,
};
std::snprintf(msgbuf, sizeof(msgbuf),
"Index %td is out of range for span of size %td", idx,
size());
throw std::out_of_range{msgbuf};
}
#endif // TCB_SPAN_NO_EXCEPTIONS
return this->operator[](idx);
}
TCB_SPAN_CONSTEXPR11 reference front() const
{
TCB_SPAN_EXPECT(!empty());
return *data();
}
TCB_SPAN_CONSTEXPR11 reference back() const
{
TCB_SPAN_EXPECT(!empty());
return *(data() + (size() - 1));
}
#endif // TCB_SPAN_STD_COMPLIANT_MODE
#ifndef TCB_SPAN_NO_FUNCTION_CALL_OPERATOR
TCB_SPAN_DEPRECATED_FOR("Use operator[] instead")
constexpr reference operator()(index_type idx) const
{
return this->operator[](idx);
}
#endif // TCB_SPAN_NO_FUNCTION_CALL_OPERATOR
constexpr pointer data() const noexcept { return storage_.ptr; }
// [span.iterators], span iterator support
constexpr iterator begin() const noexcept { return data(); }
constexpr iterator end() const noexcept { return data() + size(); }
constexpr const_iterator cbegin() const noexcept { return begin(); }
constexpr const_iterator cend() const noexcept { return end(); }
TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
{
return reverse_iterator(end());
}
TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
{
return reverse_iterator(begin());
}
TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crbegin() const noexcept
{
return const_reverse_iterator(cend());
}
TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crend() const noexcept
{
return const_reverse_iterator(cbegin());
}
private:
storage_type storage_{};
};
#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
/* Deduction Guides */
template <class T, size_t N>
span(T (&)[N])->span<T, N>;
template <class T, size_t N>
span(std::array<T, N>&)->span<T, N>;
template <class T, size_t N>
span(const std::array<T, N>&)->span<const T, N>;
template <class Container>
span(Container&)->span<typename Container::value_type>;
template <class Container>
span(const Container&)->span<const typename Container::value_type>;
#endif // TCB_HAVE_DEDUCTION_GUIDES
template <typename ElementType, std::ptrdiff_t Extent>
constexpr span<ElementType, Extent>
make_span(span<ElementType, Extent> s) noexcept
{
return s;
}
#define AS_SIGNED(N) static_cast<std::ptrdiff_t>(N)
template <typename T, std::size_t N>
constexpr span<T, AS_SIGNED(N)> make_span(T (&arr)[N]) noexcept
{
return {arr};
}
template <typename T, std::size_t N>
TCB_SPAN_ARRAY_CONSTEXPR span<T, AS_SIGNED(N)> make_span(std::array<T, N>& arr) noexcept
{
return {arr};
}
template <typename T, std::size_t N>
TCB_SPAN_ARRAY_CONSTEXPR span<const T, AS_SIGNED(N)>
make_span(const std::array<T, N>& arr) noexcept
{
return {arr};
}
#undef AS_SIGNED
template <typename Container>
constexpr span<typename Container::value_type> make_span(Container& cont)
{
return {cont};
}
template <typename Container>
constexpr span<const typename Container::value_type>
make_span(const Container& cont)
{
return {cont};
}
/* Comparison operators */
// Implementation note: the implementations of == and < are equivalent to
// 4-legged std::equal and std::lexicographical_compare respectively
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator==(span<T, X> lhs, span<U, Y> rhs)
{
if (lhs.size() != rhs.size()) {
return false;
}
for (std::ptrdiff_t i = 0; i < lhs.size(); i++) {
if (lhs[i] != rhs[i]) {
return false;
}
}
return true;
}
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator!=(span<T, X> lhs, span<U, Y> rhs)
{
return !(lhs == rhs);
}
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator<(span<T, X> lhs, span<U, Y> rhs)
{
// No std::min to avoid dragging in <algorithm>
const std::ptrdiff_t size =
lhs.size() < rhs.size() ? lhs.size() : rhs.size();
for (std::ptrdiff_t i = 0; i < size; i++) {
if (lhs[i] < rhs[i]) {
return true;
}
if (lhs[i] > rhs[i]) {
return false;
}
}
return lhs.size() < rhs.size();
}
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator<=(span<T, X> lhs, span<U, Y> rhs)
{
return !(rhs < lhs);
}
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator>(span<T, X> lhs, span<U, Y> rhs)
{
return rhs < lhs;
}
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
TCB_SPAN_CONSTEXPR14 bool operator>=(span<T, X> lhs, span<U, Y> rhs)
{
return !(lhs < rhs);
}
template <typename ElementType, std::ptrdiff_t Extent>
span<const byte, ((Extent == dynamic_extent)
? dynamic_extent
: (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))>
as_bytes(span<ElementType, Extent> s) noexcept
{
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
}
template <
class ElementType, ptrdiff_t Extent,
typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
span<byte, ((Extent == dynamic_extent)
? dynamic_extent
: (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))>
as_writable_bytes(span<ElementType, Extent> s) noexcept
{
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
}
/* Extension: nonmember subview operations */
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
template <std::ptrdiff_t Count, typename T>
TCB_SPAN_CONSTEXPR11 auto first(T& t)
-> decltype(make_span(t).template first<Count>())
{
return make_span(t).template first<Count>();
}
template <std::ptrdiff_t Count, typename T>
TCB_SPAN_CONSTEXPR11 auto last(T& t)
-> decltype(make_span(t).template last<Count>())
{
return make_span(t).template last<Count>();
}
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent,
typename T>
TCB_SPAN_CONSTEXPR11 auto subspan(T& t)
-> decltype(make_span(t).template subspan<Offset, Count>())
{
return make_span(t).template subspan<Offset, Count>();
}
template <typename T>
TCB_SPAN_CONSTEXPR11 auto first(T& t, std::ptrdiff_t count)
-> decltype(make_span(t).first(count))
{
return make_span(t).first(count);
}
template <typename T>
TCB_SPAN_CONSTEXPR11 auto last(T& t, std::ptrdiff_t count)
-> decltype(make_span(t).last(count))
{
return make_span(t).last(count);
}
template <typename T>
TCB_SPAN_CONSTEXPR11 auto subspan(T& t, std::ptrdiff_t offset,
std::ptrdiff_t count = dynamic_extent)
-> decltype(make_span(t).subspan(offset, count))
{
return make_span(t).subspan(offset, count);
}
#endif // TCB_SPAN_STD_COMPLIANT_MODE
} // namespace TCB_SPAN_NAMESPACE_NAME
/* Extension: support for C++17 structured bindings */
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
namespace TCB_SPAN_NAMESPACE_NAME {
template <std::ptrdiff_t N, typename E, std::ptrdiff_t S>
constexpr auto get(span<E, S> s) -> decltype(s[N])
{
return s[N];
}
} // namespace TCB_SPAN_NAMESPACE_NAME
namespace std {
template <typename E, ptrdiff_t S>
class tuple_size<tcb::span<E, S>> : public integral_constant<size_t, static_cast<size_t>(S)> {};
template <typename E>
class tuple_size<tcb::span<E, tcb::dynamic_extent>>; // not defined
template <size_t N, typename E, ptrdiff_t S>
class tuple_element<N, tcb::span<E, S>> {
public:
using type = E;
};
} // end namespace std
#endif // TCB_SPAN_STD_COMPLIANT_MODE
#endif // TCB_SPAN_HPP_INCLUDED

View file

@ -1,28 +0,0 @@
/***************************************************************************
* Copyright (c) 2017, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_CONFIG_HPP
#define XTL_CONFIG_HPP
#define XTL_VERSION_MAJOR 0
#define XTL_VERSION_MINOR 6
#define XTL_VERSION_PATCH 7
#ifndef __has_feature
#define __has_feature(x) 0
#endif
// Attempt to discover whether we're being compiled with exception support
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(XTL_NO_EXCEPTIONS)
// Exceptions are enabled.
#else
// Exceptions are disabled.
#define XTL_NO_EXCEPTIONS
#endif
#endif

View file

@ -1,417 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_TYPE_TRAITS_HPP
#define XTL_TYPE_TRAITS_HPP
#include <complex>
#include <chrono>
#include <type_traits>
#include "xtl_config.hpp"
namespace xtl
{
/************************************
* arithmetic type promotion traits *
************************************/
/**
* Traits class for the result type of mixed arithmetic expressions.
* For example, <tt>promote_type<unsigned char, unsigned char>::type</tt> tells
* the user that <tt>unsigned char + unsigned char => int</tt>.
*/
template <class... T>
struct promote_type;
template <>
struct promote_type<>
{
using type = void;
};
template <class T>
struct promote_type<T>
{
using type = typename promote_type<T, T>::type;
};
template <class C, class D1, class D2>
struct promote_type<std::chrono::time_point<C, D1>, std::chrono::time_point<C, D2>>
{
using type = std::chrono::time_point<C, typename promote_type<D1, D2>::type>;
};
template <class T0, class T1>
struct promote_type<T0, T1>
{
using type = decltype(std::declval<std::decay_t<T0>>() + std::declval<std::decay_t<T1>>());
};
template <class T0, class... REST>
struct promote_type<T0, REST...>
{
using type = decltype(std::declval<std::decay_t<T0>>() + std::declval<typename promote_type<REST...>::type>());
};
template <>
struct promote_type<bool>
{
using type = bool;
};
template <class T>
struct promote_type<bool, T>
{
using type = T;
};
template <class T>
struct promote_type<bool, std::complex<T>>
{
using type = std::complex<T>;
};
template <class T1, class T2>
struct promote_type<T1, std::complex<T2>>
{
using type = std::complex<typename promote_type<T1, T2>::type>;
};
template <class T1, class T2>
struct promote_type<std::complex<T1>, T2>
: promote_type<T2, std::complex<T1>>
{
};
template <class T>
struct promote_type<std::complex<T>, std::complex<T>>
{
using type = std::complex<T>;
};
template <class... REST>
struct promote_type<bool, REST...>
{
using type = typename promote_type<bool, typename promote_type<REST...>::type>::type;
};
/**
* Abbreviation of 'typename promote_type<T>::type'.
*/
template <class... T>
using promote_type_t = typename promote_type<T...>::type;
/**
* Traits class to find the biggest type of the same kind.
*
* For example, <tt>big_promote_type<unsigned char>::type</tt> is <tt>unsigned long long</tt>.
* The default implementation only supports built-in types and <tt>std::complex</tt>. All
* other types remain unchanged unless <tt>big_promote_type</tt> gets specialized for them.
*/
template <class T>
struct big_promote_type
{
private:
using V = std::decay_t<T>;
static constexpr bool is_arithmetic = std::is_arithmetic<V>::value;
static constexpr bool is_signed = std::is_signed<V>::value;
static constexpr bool is_integral = std::is_integral<V>::value;
static constexpr bool is_long_double = std::is_same<V, long double>::value;
public:
using type = std::conditional_t<is_arithmetic,
std::conditional_t<is_integral,
std::conditional_t<is_signed, long long, unsigned long long>,
std::conditional_t<is_long_double, long double, double>
>,
V
>;
};
template <class T>
struct big_promote_type<std::complex<T>>
{
using type = std::complex<typename big_promote_type<T>::type>;
};
/**
* Abbreviation of 'typename big_promote_type<T>::type'.
*/
template <class T>
using big_promote_type_t = typename big_promote_type<T>::type;
namespace traits_detail
{
using std::sqrt;
template <class T>
using real_promote_type_t = decltype(sqrt(std::declval<std::decay_t<T>>()));
}
/**
* Result type of algebraic expressions.
*
* For example, <tt>real_promote_type<int>::type</tt> tells the
* user that <tt>sqrt(int) => double</tt>.
*/
template <class T>
struct real_promote_type
{
using type = traits_detail::real_promote_type_t<T>;
};
/**
* Abbreviation of 'typename real_promote_type<T>::type'.
*/
template <class T>
using real_promote_type_t = typename real_promote_type<T>::type;
/**
* Traits class to replace 'bool' with 'uint8_t' and keep everything else.
*
* This is useful for scientific computing, where a boolean mask array is
* usually implemented as an array of bytes.
*/
template <class T>
struct bool_promote_type
{
using type = typename std::conditional<std::is_same<T, bool>::value, uint8_t, T>::type;
};
/**
* Abbreviation for typename bool_promote_type<T>::type
*/
template <class T>
using bool_promote_type_t = typename bool_promote_type<T>::type;
/************
* apply_cv *
************/
namespace detail
{
template <class T, class U, bool = std::is_const<std::remove_reference_t<T>>::value,
bool = std::is_volatile<std::remove_reference_t<T>>::value>
struct apply_cv_impl
{
using type = U;
};
template <class T, class U>
struct apply_cv_impl<T, U, true, false>
{
using type = const U;
};
template <class T, class U>
struct apply_cv_impl<T, U, false, true>
{
using type = volatile U;
};
template <class T, class U>
struct apply_cv_impl<T, U, true, true>
{
using type = const volatile U;
};
template <class T, class U>
struct apply_cv_impl<T&, U, false, false>
{
using type = U&;
};
template <class T, class U>
struct apply_cv_impl<T&, U, true, false>
{
using type = const U&;
};
template <class T, class U>
struct apply_cv_impl<T&, U, false, true>
{
using type = volatile U&;
};
template <class T, class U>
struct apply_cv_impl<T&, U, true, true>
{
using type = const volatile U&;
};
}
template <class T, class U>
struct apply_cv
{
using type = typename detail::apply_cv_impl<T, U>::type;
};
template <class T, class U>
using apply_cv_t = typename apply_cv<T, U>::type;
/****************************************************************
* C++17 logical operators (disjunction, conjunction, negation) *
****************************************************************/
/********************
* disjunction - or *
********************/
template <class...>
struct disjunction;
template <>
struct disjunction<> : std::false_type
{
};
template <class Arg>
struct disjunction<Arg> : Arg
{
};
template <class Arg1, class Arg2, class... Args>
struct disjunction<Arg1, Arg2, Args...> : std::conditional_t<Arg1::value, Arg1, disjunction<Arg2, Args...>>
{
};
/*********************
* conjunction - and *
*********************/
template <class...>
struct conjunction;
template <>
struct conjunction<> : std::true_type
{
};
template <class Arg1>
struct conjunction<Arg1> : Arg1
{
};
template <class Arg1, class Arg2, class... Args>
struct conjunction<Arg1, Arg2, Args...> : std::conditional_t<Arg1::value, conjunction<Arg2, Args...>, Arg1>
{
};
/******************
* negation - not *
******************/
template <class Arg>
struct negation : std::integral_constant<bool, !Arg::value>
{
};
/************
* concepts *
************/
#if !defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ >= 5))
template <class... C>
constexpr bool requires = conjunction<C...>::value;
template <class... C>
constexpr bool either = disjunction<C...>::value;
template <class... C>
constexpr bool disallow = xtl::negation<xtl::conjunction<C...>>::value;
template <class... C>
constexpr bool disallow_one = xtl::negation<xtl::disjunction<C...>>::value;
template <class... C>
using check_requires = std::enable_if_t<requires<C...>, int>;
template <class... C>
using check_either = std::enable_if_t<either<C...>, int>;
template <class... C>
using check_disallow = std::enable_if_t<disallow<C...>, int>;
template <class... C>
using check_disallow_one = std::enable_if_t<disallow_one<C...>, int>;
#else
template <class... C>
using check_requires = std::enable_if_t<conjunction<C...>::value, int>;
template <class... C>
using check_either = std::enable_if_t<disjunction<C...>::value, int>;
template <class... C>
using check_disallow = std::enable_if_t<xtl::negation<xtl::conjunction<C...>>::value, int>;
template <class... C>
using check_disallow_one = std::enable_if_t<xtl::negation<xtl::disjunction<C...>>::value, int>;
#endif
#define XTL_REQUIRES_IMPL(...) xtl::check_requires<__VA_ARGS__>
#define XTL_REQUIRES(...) XTL_REQUIRES_IMPL(__VA_ARGS__) = 0
#define XTL_EITHER_IMPL(...) xtl::check_either<__VA_ARGS__>
#define XTL_EITHER(...) XTL_EITHER_IMPL(__VA_ARGS__) = 0
#define XTL_DISALLOW_IMPL(...) xtl::check_disallow<__VA_ARGS__>
#define XTL_DISALLOW(...) XTL_DISALLOW_IMPL(__VA_ARGS__) = 0
#define XTL_DISALLOW_ONE_IMPL(...) xtl::check_disallow_one<__VA_ARGS__>
#define XTL_DISALLOW_ONE(...) XTL_DISALLOW_ONE_IMPL(__VA_ARGS__) = 0
// For backward compatibility
template <class... C>
using check_concept = check_requires<C...>;
/**************
* all_scalar *
**************/
template <class... Args>
struct all_scalar : conjunction<std::is_scalar<Args>...>
{
};
/************
* constify *
************/
// Adds const to the underlying type of a reference or pointer, or to the type itself
// if it's not a reference nor a pointer
template <class T>
struct constify
{
using type = std::add_const_t<T>;
};
template <class T>
struct constify<T*>
{
using type = std::add_const_t<T>*;
};
template <class T>
struct constify<T&>
{
using type = std::add_const_t<T>&;
};
template <class T>
using constify_t = typename constify<T>::type;
}
#endif

View file

@ -1,205 +0,0 @@
/***************************************************************************
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#ifndef XTL_XVARIANT_HPP
#define XTL_XVARIANT_HPP
#include "xvariant_impl.hpp"
#include "xclosure.hpp"
#include "xmeta_utils.hpp"
namespace xtl
{
using mpark::variant;
using mpark::monostate;
using mpark::bad_variant_access;
using mpark::variant_size;
#ifdef MPARK_VARIABLE_TEMPLATES
using mpark::variant_size_v;
#endif
using mpark::variant_alternative;
using mpark::variant_alternative_t;
using mpark::variant_npos;
using mpark::visit;
using mpark::holds_alternative;
using mpark::get;
using mpark::get_if;
namespace detail
{
template <class T>
struct xgetter
{
template <class... Ts>
static constexpr T& get(xtl::variant<Ts...>& v)
{
return xtl::get<T>(v);
}
template <class... Ts>
static constexpr T&& get(xtl::variant<Ts...>&& v)
{
return xtl::get<T>(std::move(v));
}
template <class... Ts>
static constexpr const T& get(const xtl::variant<Ts...>& v)
{
return xtl::get<T>(v);
}
template <class... Ts>
static constexpr const T&& get(const xtl::variant<Ts...>&& v)
{
return xtl::get<T>(std::move(v));
}
};
template <class T>
struct xgetter<T&>
{
template <class... Ts>
static constexpr T& get(xtl::variant<Ts...>& v)
{
return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
}
template <class... Ts>
static constexpr T& get(xtl::variant<Ts...>&& v)
{
return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
}
template <class... Ts>
static constexpr const T& get(const xtl::variant<Ts...>& v)
{
return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
}
template <class... Ts>
static constexpr const T& get(const xtl::variant<Ts...>&& v)
{
return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
}
};
template <class T>
struct xgetter<const T&>
{
template <class... Ts>
static constexpr const T& get(const xtl::variant<Ts...>& v)
{
using cl_type = xtl::xclosure_wrapper<const T&>;
return get_impl(v, xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
}
template <class... Ts>
static constexpr const T& get(const xtl::variant<Ts...>&& v)
{
using cl_type = xtl::xclosure_wrapper<const T&>;
return get_impl(std::move(v), xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
}
template <class... Ts>
static constexpr const T& get(xtl::variant<Ts...>& v)
{
return get(static_cast<const xtl::variant<Ts...>&>(v));
}
template <class... Ts>
static constexpr const T& get(xtl::variant<Ts...>&& v)
{
return get(static_cast<const xtl::variant<Ts...>&&>(v));
}
private:
template <class... Ts>
static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<true>)
{
return xtl::get<xtl::xclosure_wrapper<const T&>>(v).get();
}
template <class... Ts>
static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<false>)
{
return static_cast<const xtl::xclosure_wrapper<T&>&>(xtl::get<xtl::xclosure_wrapper<T&>>(v)).get();
}
template <class... Ts>
static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<true>)
{
return xtl::get<xtl::closure_wrapper<const T&>>(std::move(v)).get();
}
template <class... Ts>
static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<false>)
{
return static_cast<const xtl::xclosure_wrapper<T&>&&>(xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v))).get();
}
};
}
template <class T, class... Ts>
constexpr decltype(auto) xget(xtl::variant<Ts...>& v)
{
return detail::xgetter<T>::get(v);
}
template <class T, class... Ts>
constexpr decltype(auto) xget(xtl::variant<Ts...>&& v)
{
return detail::xgetter<T>::get(std::move(v));
}
template <class T, class... Ts>
constexpr decltype(auto) xget(const xtl::variant<Ts...>& v)
{
return detail::xgetter<T>::get(v);
}
template <class T, class... Ts>
constexpr decltype(auto) xget(const xtl::variant<Ts...>&& v)
{
return detail::xgetter<T>::get(std::move(v));
}
/************************
* overload for lambdas *
************************/
// This hierarchy is required since ellipsis in using declarations are not supported until C++17
template <class... Ts>
struct overloaded;
template <class T>
struct overloaded<T> : T
{
overloaded(T arg) : T(arg) {}
using T::operator();
};
template <class T1, class T2, class... Ts>
struct overloaded<T1, T2, Ts...> : T1, overloaded<T2, Ts...>
{
template <class... Us>
overloaded(T1 t1, T2 t2, Us... args) : T1(t1), overloaded<T2, Ts...>(t2, args...) {}
using T1::operator();
using overloaded<T2, Ts...>::operator();
};
template <class... Ts>
inline overloaded<Ts...> make_overload(Ts... arg)
{
return overloaded<Ts...>{arg...};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/include
Name: xtl
Description: Basic tools (containers, algorithms) used by other quantstack packages.
Version: @xtl_VERSION@
Cflags: -I${includedir}

View file

@ -1,21 +0,0 @@
############################################################################
# Copyright (c) 2017, Sylvain Corlay and Johan Mabille #
# #
# Distributed under the terms of the BSD 3-Clause License. #
# #
# The full license is in the file LICENSE, distributed with this software. #
############################################################################
# xtl cmake module
# This module sets the following variables in your project::
#
# xtl_FOUND - true if xtl found on the system
# xtl_INCLUDE_DIRS - the directory containing xtl headers
# xtl_LIBRARY - empty
@PACKAGE_INIT@
if(NOT TARGET @PROJECT_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
get_target_property(@PROJECT_NAME@_INCLUDE_DIRS xtl INTERFACE_INCLUDE_DIRECTORIES)
endif()