Init. "MIDI library for pico-sdk, extracted from Control-Surface"
This commit is contained in:
commit
99fdfb2600
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Math/MinMaxFix.hpp>
|
||||
#include "../platform/pico_shim.h"
|
||||
|
|
@ -0,0 +1,533 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Error/Error.hpp>
|
||||
#include <AH/STL/iterator>
|
||||
#include <AH/STL/type_traits> // conditional
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
template <class T>
|
||||
constexpr T abs_diff(const T &a, const T &b) {
|
||||
return a < b ? b - a : a - b;
|
||||
}
|
||||
|
||||
/// @addtogroup AH_Containers
|
||||
/// @{
|
||||
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
class ArraySlice;
|
||||
|
||||
/**
|
||||
* @brief An array wrapper for easy copying, comparing, and iterating.
|
||||
*
|
||||
* @tparam T
|
||||
* The type of the elements in the array.
|
||||
* @tparam N
|
||||
* The number of elements in the array.
|
||||
*/
|
||||
template <class T, size_t N>
|
||||
struct Array {
|
||||
T data[N];
|
||||
using type = T;
|
||||
constexpr static size_t length = N;
|
||||
|
||||
/**
|
||||
* @brief Get the element at the given index.
|
||||
*
|
||||
* @note Bounds checking is performed. If fatal errors are disabled, the
|
||||
* last element is returned if the index is out of bounds.
|
||||
*
|
||||
* @param index
|
||||
* The (zero-based) index of the element to return.
|
||||
*/
|
||||
T &operator[](size_t index) {
|
||||
if (index >= N) { // TODO
|
||||
ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDED);
|
||||
index = N - 1; // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
return data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the element at the given index.
|
||||
*
|
||||
* @note Bounds checking is performed. If fatal errors are disabled, the
|
||||
* last element is returned if the index is out of bounds.
|
||||
*
|
||||
* @param index
|
||||
* The (zero-based) index of the element to return.
|
||||
*/
|
||||
const T &operator[](size_t index) const {
|
||||
if (index >= N) { // TODO
|
||||
ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDED);
|
||||
index = N - 1; // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
return data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the first element.
|
||||
*/
|
||||
T *begin() { return &data[0]; }
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the first element.
|
||||
*/
|
||||
const T *begin() const { return &data[0]; }
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the memory beyond the array.
|
||||
*/
|
||||
T *end() { return &data[N]; }
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the memory beyond the array.
|
||||
*/
|
||||
const T *end() const { return &data[N]; }
|
||||
|
||||
/**
|
||||
* @brief Check the equality of all elements in two arrays.
|
||||
*
|
||||
* @param rhs
|
||||
* The array to compare this array to.
|
||||
*/
|
||||
bool operator==(const Array<T, N> &rhs) const {
|
||||
if (this == &rhs)
|
||||
return true;
|
||||
for (size_t i = 0; i < N; i++)
|
||||
if ((*this)[i] != rhs[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the inequality of all elements in two arrays.
|
||||
*
|
||||
* @param rhs
|
||||
* The array to compare this array to.
|
||||
*/
|
||||
bool operator!=(const Array<T, N> &rhs) const { return !(*this == rhs); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get a view on a slice of the Array.
|
||||
*
|
||||
* Doesn't copy the contents of the array, it's just a reference to the
|
||||
* original array.
|
||||
*
|
||||
* @tparam Start
|
||||
* The start index of the slice.
|
||||
* @tparam End
|
||||
* The end index of the slice.
|
||||
*/
|
||||
template <size_t Start = 0, size_t End = N - 1>
|
||||
ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), false> slice();
|
||||
|
||||
/**
|
||||
* @brief Get a read-only view on a slice of the Array.
|
||||
* @copydetails slice()
|
||||
*/
|
||||
template <size_t Start = 0, size_t End = N - 1>
|
||||
ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true> slice() const;
|
||||
|
||||
/**
|
||||
* @brief Get a read-only view on a slice of the Array.
|
||||
* @copydetails slice()
|
||||
*/
|
||||
template <size_t Start = 0, size_t End = N - 1>
|
||||
ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true>
|
||||
cslice() const {
|
||||
const Array<T, N> *This = this;
|
||||
return This->template slice<Start, End>();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for a view on a slice of an array.
|
||||
*
|
||||
* Doesn't copy the contents of the array, it's just a reference to the original
|
||||
* array.
|
||||
*
|
||||
* @tparam T
|
||||
* The type of elements of the Array.
|
||||
* @tparam N
|
||||
* The size of the slice.
|
||||
* @tparam Reverse
|
||||
* Whether the slice is reversed or not.
|
||||
* @tparam Const
|
||||
* Whether to save a read-only or mutable reference to the Array.
|
||||
*/
|
||||
template <class T, size_t N, bool Reverse = false, bool Const = true>
|
||||
class ArraySlice {
|
||||
using ElementRefType =
|
||||
typename std::conditional<Const, const T &, T &>::type;
|
||||
using ElementPtrType =
|
||||
typename std::conditional<Const, const T *, T *>::type;
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
ArraySlice(ElementPtrType array) : array {array} {}
|
||||
|
||||
/// Implicit conversion from slice to new array (creates a copy).
|
||||
operator Array<T, N>() const { return asArray(); }
|
||||
|
||||
Array<T, N> asArray() const {
|
||||
Array<T, N> slice = {{}};
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
slice[i] = (*this)[i];
|
||||
return slice;
|
||||
}
|
||||
|
||||
using iterator = typename std::conditional<
|
||||
Reverse, std::reverse_iterator<ElementPtrType>, ElementPtrType>::type;
|
||||
|
||||
/**
|
||||
* @brief Get the element at the given index.
|
||||
*
|
||||
* @note Bounds checking is performed. If fatal errors are disabled, the
|
||||
* last element is returned if the index is out of bounds.
|
||||
*
|
||||
* @param index
|
||||
* The (zero-based) index of the element to return.
|
||||
*/
|
||||
ElementRefType operator[](size_t index) const {
|
||||
if (index >= N) { // TODO
|
||||
ERROR(F("Index out of bounds: ") << index << F(" ≥ ") << N, 0xEDEF);
|
||||
index = N - 1; // LCOV_EXCL_LINE
|
||||
} // LCOV_EXCL_LINE
|
||||
if (Reverse)
|
||||
return *(array - index);
|
||||
else
|
||||
return *(array + index);
|
||||
}
|
||||
|
||||
iterator begin() const {
|
||||
if (Reverse)
|
||||
return iterator {array + 1};
|
||||
else
|
||||
return iterator {array};
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
if (Reverse)
|
||||
return iterator {array + 1 - N};
|
||||
else
|
||||
return iterator {array + N};
|
||||
}
|
||||
|
||||
template <size_t Start, size_t End>
|
||||
ArraySlice<T, abs_diff(End, Start) + 1, Reverse ^ (End < Start), Const>
|
||||
slice() const;
|
||||
|
||||
private:
|
||||
ElementPtrType array;
|
||||
};
|
||||
|
||||
template <class T, size_t N>
|
||||
template <size_t Start, size_t End>
|
||||
auto Array<T, N>::slice()
|
||||
-> ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), false> {
|
||||
static_assert(Start < N, "");
|
||||
static_assert(End < N, "");
|
||||
return &(*this)[Start];
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
template <size_t Start, size_t End>
|
||||
auto Array<T, N>::slice() const
|
||||
-> ArraySlice<T, abs_diff(Start, End) + 1, (End < Start), true> {
|
||||
static_assert(Start < N, "");
|
||||
static_assert(End < N, "");
|
||||
return &(*this)[Start];
|
||||
}
|
||||
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
template <size_t Start, size_t End>
|
||||
auto ArraySlice<T, N, Reverse, Const>::slice() const
|
||||
-> ArraySlice<T, abs_diff(End, Start) + 1, Reverse ^ (End < Start), Const> {
|
||||
static_assert(Start < N, "");
|
||||
static_assert(End < N, "");
|
||||
return &(*this)[Start];
|
||||
}
|
||||
|
||||
/// @related ArraySlice<T, N, Reverse, Const>::iterator
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
typename ArraySlice<T, N, Reverse, Const>::iterator operator+(
|
||||
typename ArraySlice<T, N, Reverse, Const>::iterator::difference_type n,
|
||||
typename ArraySlice<T, N, Reverse, Const>::iterator a) {
|
||||
return a + n;
|
||||
}
|
||||
|
||||
// Equality ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice == Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
bool operator==(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
static_assert(N1 == N2, "Error: sizes do not match");
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Array == Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
|
||||
bool operator==(const Array<T1, N1> &a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
return a.slice() == b;
|
||||
}
|
||||
|
||||
/// Slice == Array
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
|
||||
bool operator==(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
const Array<T2, N2> &b) {
|
||||
return a == b.slice();
|
||||
}
|
||||
|
||||
// Inequality ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice != Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
bool operator!=(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
/// Array != Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
|
||||
bool operator!=(const Array<T1, N1> &a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
return a.slice() != b;
|
||||
}
|
||||
|
||||
/// Slice != Array
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
|
||||
bool operator!=(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
const Array<T2, N2> &b) {
|
||||
return a != b.slice();
|
||||
}
|
||||
|
||||
// Addition ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice + Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
Array<decltype(T1 {} + T2 {}), N1>
|
||||
operator+(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
static_assert(N1 == N2, "Error: sizes do not match");
|
||||
Array<decltype(T1 {} + T2 {}), N1> result = {{}};
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
result[i] = a[i] + b[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Array + Array
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1, size_t N2>
|
||||
Array<decltype(T1 {} + T2 {}), N1> operator+(const Array<T1, N1> &a,
|
||||
const Array<T2, N2> &b) {
|
||||
return a.slice() + b.slice();
|
||||
}
|
||||
|
||||
/// Slice += Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
const ArraySlice<T1, N1, Reverse1, Const1> &
|
||||
operator+=(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
||||
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
||||
static_assert(N1 == N2, "Error: sizes do not match");
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
a[i] += b[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
/// Array += Array
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1, size_t N2>
|
||||
Array<T1, N1> &operator+=(Array<T1, N1> &a, const Array<T2, N2> &b) {
|
||||
a.slice() += b.slice();
|
||||
return a;
|
||||
}
|
||||
|
||||
// Subtraction :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice - Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
Array<decltype(T1 {} - T2 {}), N1>
|
||||
operator-(ArraySlice<T1, N1, Reverse1, Const1> a,
|
||||
ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
static_assert(N1 == N2, "Error: sizes do not match");
|
||||
Array<decltype(T1 {} - T2 {}), N1> result = {{}};
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
result[i] = a[i] - b[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Array - Array
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1, size_t N2>
|
||||
Array<decltype(T1 {} - T2 {}), N1> operator-(const Array<T1, N1> &a,
|
||||
const Array<T2, N2> &b) {
|
||||
return a.slice() - b.slice();
|
||||
}
|
||||
|
||||
/// Slice -= Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
const ArraySlice<T1, N1, Reverse1, Const1> &
|
||||
operator-=(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
||||
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
||||
static_assert(N1 == N2, "Error: sizes do not match");
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
a[i] -= b[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
/// Array -= Array
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1, size_t N2>
|
||||
Array<T1, N1> &operator-=(Array<T1, N1> &a, const Array<T2, N2> &b) {
|
||||
a.slice() -= b.slice();
|
||||
return a;
|
||||
}
|
||||
|
||||
// Scalar Multiplication :::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice * Scalar
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
|
||||
Array<decltype(T1 {} * T2 {}), N1>
|
||||
operator*(ArraySlice<T1, N1, Reverse1, Const1> a, T2 b) {
|
||||
Array<decltype(T1 {} * T2 {}), N1> result = {{}};
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
result[i] = a[i] * b;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Array * Scalar
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1>
|
||||
Array<decltype(T1 {} * T2 {}), N1> operator*(const Array<T1, N1> &a, T2 b) {
|
||||
return a.slice() * b;
|
||||
}
|
||||
|
||||
/// Scalar * Slice
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N2, bool Reverse2, bool Const2>
|
||||
Array<decltype(T1 {} * T2 {}), N2>
|
||||
operator*(T1 a, ArraySlice<T2, N2, Reverse2, Const2> b) {
|
||||
Array<decltype(T1 {} * T2 {}), N2> result = {{}};
|
||||
for (size_t i = 0; i < N2; ++i)
|
||||
result[i] = a * b[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Scalar * Array
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N2>
|
||||
Array<decltype(T1 {} * T2 {}), N2> operator*(T1 a, const Array<T2, N2> &b) {
|
||||
return a * b.slice();
|
||||
}
|
||||
|
||||
/// Slice *= Scalar
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
|
||||
const ArraySlice<T1, N1, Reverse1, Const1> &
|
||||
operator*=(const ArraySlice<T1, N1, Reverse1, Const1> &a, T2 b) {
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
a[i] *= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// Array *= Scalar
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1>
|
||||
Array<T1, N1> &operator*=(Array<T1, N1> &a, T2 b) {
|
||||
a.slice() *= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
// Scalar Division :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Slice / Scalar
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
|
||||
Array<decltype(T1 {} / T2 {}), N1>
|
||||
operator/(ArraySlice<T1, N1, Reverse1, Const1> a, T2 b) {
|
||||
Array<decltype(T1 {} / T2 {}), N1> result = {{}};
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
result[i] = a[i] / b;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Array / Scalar
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1>
|
||||
Array<decltype(T1 {} / T2 {}), N1> operator/(const Array<T1, N1> &a, T2 b) {
|
||||
return a.slice() / b;
|
||||
}
|
||||
|
||||
/// Slice /= Scalar
|
||||
/// @related ArraySlice
|
||||
template <class T1, class T2, size_t N1, bool Reverse1, bool Const1>
|
||||
const ArraySlice<T1, N1, Reverse1, Const1> &
|
||||
operator/=(const ArraySlice<T1, N1, Reverse1, Const1> &a, T2 b) {
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
a[i] /= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// Array /= Scalar
|
||||
/// @related Array
|
||||
template <class T1, class T2, size_t N1>
|
||||
Array<T1, N1> &operator/=(Array<T1, N1> &a, T2 b) {
|
||||
a.slice() /= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
// Negation ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// -Slice
|
||||
/// @related ArraySlice
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
Array<decltype(-T {}), N> operator-(ArraySlice<T, N, Reverse, Const> a) {
|
||||
Array<decltype(-T {}), N> result = {{}};
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
result[i] = -a[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// -Array
|
||||
/// @related Array
|
||||
template <class T, size_t N>
|
||||
Array<decltype(-T {}), N> operator-(const Array<T, N> &a) {
|
||||
return -a.slice();
|
||||
}
|
||||
|
||||
// Type aliases ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// An easy alias for two-dimensional Arrays.
|
||||
template <class T, size_t NumRows, size_t NumCols>
|
||||
using Array2D = Array<Array<T, NumCols>, NumRows>;
|
||||
|
||||
/// @}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
#pragma once
|
||||
|
||||
#include "Array.hpp"
|
||||
#include <AH/STL/algorithm>
|
||||
|
||||
#if __cplusplus >= 201400L
|
||||
#define USE_CONSTEXPR_ARRAY_HELPERS constexpr
|
||||
#else
|
||||
#define USE_CONSTEXPR_ARRAY_HELPERS
|
||||
#endif
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T, class V>
|
||||
class Incrementor {
|
||||
public:
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Incrementor(T start = 0, V increment = 1)
|
||||
: value(start), increment(increment) {}
|
||||
USE_CONSTEXPR_ARRAY_HELPERS T operator()() {
|
||||
T temp = value;
|
||||
value += increment;
|
||||
return temp;
|
||||
}
|
||||
|
||||
private:
|
||||
T value;
|
||||
const V increment;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, size_t N, class G>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> generateArray(G generator) {
|
||||
Array<T, N> array{{}};
|
||||
std::generate(array.begin(), array.end(), generator);
|
||||
return array;
|
||||
}
|
||||
|
||||
template <size_t N, class G>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS auto generateArray(G generator)
|
||||
-> Array<decltype(generator()), N> {
|
||||
Array<decltype(generator()), N> array{{}};
|
||||
std::generate(array.begin(), array.end(), generator);
|
||||
return array;
|
||||
}
|
||||
|
||||
template <class T, size_t N, class U>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> copyAs(const Array<U, N> &src) {
|
||||
Array<T, N> dest{{}};
|
||||
std::transform(std::begin(src), std::end(src), std::begin(dest),
|
||||
[](const U &src) { return T(src); });
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class F, class U, size_t N>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(F{}(U{})), N>
|
||||
apply(const Array<U, N> &src, F f) {
|
||||
Array<decltype(F{}(U{})), N> dest{{}};
|
||||
std::transform(std::begin(src), std::end(src), std::begin(dest), f);
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class T, size_t N, class... Args>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N> fillArray(Args... args) {
|
||||
return generateArray<N>([&]() { return T{args...}; });
|
||||
}
|
||||
|
||||
template <class T, size_t N, class U, class V = U>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<T, N>
|
||||
generateIncrementalArray(U start = 0, V increment = V(1)) {
|
||||
detail::Incrementor<U, V> g(start, increment);
|
||||
return generateArray<T, N>(g);
|
||||
}
|
||||
|
||||
template <class T, size_t M, size_t N>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<T, M + N> cat(const Array<T, M> &a,
|
||||
const Array<T, N> &b) {
|
||||
Array<T, M + N> result{{}};
|
||||
size_t r = 0;
|
||||
for (size_t i = 0; i < M; ++i, ++r)
|
||||
result[r] = a[i];
|
||||
for (size_t i = 0; i < N; ++i, ++r)
|
||||
result[r] = b[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1,
|
||||
bool Reverse2, bool Const1, bool Const2>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
||||
distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
||||
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
||||
Array<decltype(T1() * T2()), N1 + N2 - 1> result = {{}};
|
||||
for (size_t i = 0; i < N1; ++i)
|
||||
for (size_t j = 0; j < N2; ++j)
|
||||
result[i + j] += a[i] * b[j];
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse1, bool Const1>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
||||
distribute(const ArraySlice<T1, N1, Reverse1, Const1> &a,
|
||||
const Array<T2, N2> &b) {
|
||||
return distribute(a, b.slice());
|
||||
}
|
||||
|
||||
template <class T1, class T2, size_t N1, size_t N2, bool Reverse2, bool Const2>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
||||
distribute(const Array<T1, N1> &a,
|
||||
const ArraySlice<T2, N2, Reverse2, Const2> &b) {
|
||||
return distribute(a.slice(), b);
|
||||
}
|
||||
|
||||
template <class T1, class T2, size_t N1, size_t N2>
|
||||
USE_CONSTEXPR_ARRAY_HELPERS Array<decltype(T1() * T2()), N1 + N2 - 1>
|
||||
distribute(const Array<T1, N1> &a, const Array<T2, N2> &b) {
|
||||
return distribute(a.slice(), b.slice());
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <ostream>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
|
||||
operator<<(std::ostream &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
|
||||
for (const T &el : a.template slice<0, N - 2>())
|
||||
os << el << ", ";
|
||||
os << a[N - 1];
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, std::ostream &>
|
||||
operator<<(std::ostream &os, const AH::Array<T, N> &a) {
|
||||
return os << a.slice();
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
||||
#include <AH/PrintStream/PrintStream.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
template <class T, size_t N, bool Reverse, bool Const>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, Print &>
|
||||
operator<<(Print &os, const AH::ArraySlice<T, N, Reverse, Const> &a) {
|
||||
for (const T &el : a.template slice<0, N - 2>())
|
||||
os << el << ", ";
|
||||
os << a[N - 1];
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, Print &>
|
||||
operator<<(Print &os, const AH::Array<T, N> &a) {
|
||||
return os << a.slice();
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Error/Error.hpp>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// @addtogroup AH_Containers
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief A class for arrays of bits.
|
||||
*
|
||||
* @tparam N
|
||||
* The number of bits.
|
||||
*/
|
||||
template <uint16_t N>
|
||||
class BitArray {
|
||||
public:
|
||||
/**
|
||||
* @brief Get the value of the given bit.
|
||||
*
|
||||
* @param bitIndex
|
||||
* The (zero-based) index of the bit to read.
|
||||
*/
|
||||
bool get(uint16_t bitIndex) const {
|
||||
return buffer[getBufferIndex(bitIndex)] & getBufferMask(bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the value of the given bit to 1.
|
||||
*
|
||||
* @param bitIndex
|
||||
* The (zero-based) index of the bit to set.
|
||||
*/
|
||||
void set(uint16_t bitIndex) {
|
||||
buffer[getBufferIndex(bitIndex)] |= getBufferMask(bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the value of the given bit to 0.
|
||||
*
|
||||
* @param bitIndex
|
||||
* The (zero-based) index of the bit to clear.
|
||||
*/
|
||||
void clear(uint16_t bitIndex) {
|
||||
buffer[getBufferIndex(bitIndex)] &= ~getBufferMask(bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the value of the given bit to the given state.
|
||||
*
|
||||
* @param bitIndex
|
||||
* The (zero-based) index of the bit to set.
|
||||
* @param state
|
||||
* The value to set the bit to.
|
||||
*/
|
||||
void set(uint16_t bitIndex, bool state) {
|
||||
state ? set(bitIndex) : clear(bitIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the given byte index, and return it if it is within the
|
||||
* bounds of the array, otherwise, throw an error, and return
|
||||
* the last valid index.
|
||||
*
|
||||
* @param byteIndex
|
||||
* The index to check.
|
||||
*/
|
||||
uint16_t safeIndex(uint16_t byteIndex) const {
|
||||
if (byteIndex >= getBufferLength()) {
|
||||
ERROR(F("Error: index out of bounds (")
|
||||
<< byteIndex << F(", length is ") << getBufferLength()
|
||||
<< ')',
|
||||
0xFFFF);
|
||||
return getBufferLength() - 1; // LCOV_EXCL_LINE
|
||||
}
|
||||
return byteIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the byte at the given index.
|
||||
*
|
||||
* This function can be used to quickly access all of the bits, to send
|
||||
* them out to a shift register, for example.
|
||||
*
|
||||
* @note No bounds checking is performed.
|
||||
*
|
||||
* @param byteIndex
|
||||
* The index of the byte within the array.
|
||||
*/
|
||||
const uint8_t &getByte(uint16_t byteIndex) const {
|
||||
return buffer[byteIndex];
|
||||
// return buffer[safeIndex(byteIndex)];
|
||||
}
|
||||
/// @copydoc AH::BitArray::getByte(uint16_t) const
|
||||
uint8_t &getByte(uint16_t byteIndex) {
|
||||
return buffer[byteIndex];
|
||||
// return buffer[safeIndex(byteIndex)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the byte at the given index.
|
||||
*
|
||||
* This function can be used to quickly write all of the bits, when reading
|
||||
* them in from an I/O expander, for example.
|
||||
*
|
||||
* @note No bounds checking is performed.
|
||||
*
|
||||
* @param byteIndex
|
||||
* The index of the byte within the array.
|
||||
* @param value
|
||||
* The byte to write.
|
||||
*/
|
||||
void setByte(uint16_t byteIndex, uint8_t value) {
|
||||
buffer[byteIndex] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the buffer length in bytes.
|
||||
*/
|
||||
uint16_t getBufferLength() const { return bufferLength; }
|
||||
|
||||
private:
|
||||
uint16_t getBufferIndex(uint16_t bitIndex) const {
|
||||
return safeIndex(bitIndex / 8);
|
||||
}
|
||||
uint8_t getBufferBit(uint16_t bitIndex) const { return bitIndex % 8; }
|
||||
uint8_t getBufferMask(uint16_t bitIndex) const {
|
||||
return 1 << getBufferBit(bitIndex);
|
||||
}
|
||||
|
||||
constexpr static uint16_t bufferLength = (uint16_t)((N + 7) / 8);
|
||||
uint8_t buffer[bufferLength] = {};
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
/// Helper for the Curiously Recurring Template Pattern.
|
||||
#define CRTP(Derived) (*static_cast<Derived *>(this))
|
||||
#define CRTP_INST(Derived, el) (static_cast<Derived &>(el))
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Debug/Debug.hpp>
|
||||
#include <AH/Math/MinMaxFix.hpp>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <AH/STL/iterator>
|
||||
|
||||
/// @addtogroup AH_Containers
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief A class for doubly linked lists.
|
||||
*
|
||||
* @tparam Node
|
||||
* The type of the nodes of the list.
|
||||
*/
|
||||
template <class Node>
|
||||
class DoublyLinkedList {
|
||||
public:
|
||||
/// Base class for doubly linked list iterators
|
||||
template <class INode>
|
||||
class node_iterator_base {
|
||||
public:
|
||||
node_iterator_base(INode *node) : node(node) {}
|
||||
|
||||
bool operator!=(const node_iterator_base &rhs) const {
|
||||
return node != rhs.node;
|
||||
}
|
||||
|
||||
bool operator==(const node_iterator_base &rhs) const {
|
||||
return !(*this != rhs);
|
||||
}
|
||||
|
||||
INode &operator*() const {
|
||||
// TODO: check node != nullptr
|
||||
return *node;
|
||||
}
|
||||
|
||||
INode *operator->() const {
|
||||
// TODO: check node != nullptr
|
||||
return node;
|
||||
}
|
||||
|
||||
protected:
|
||||
INode *node;
|
||||
};
|
||||
|
||||
/// Forward bidirectional doubly linked list iterator
|
||||
template <class INode>
|
||||
class node_iterator : public node_iterator_base<INode> {
|
||||
public:
|
||||
node_iterator(INode *node) : node_iterator_base<INode>(node) {}
|
||||
|
||||
using difference_type = long;
|
||||
using value_type = INode;
|
||||
using pointer = INode *;
|
||||
using reference = INode &;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
/// Prefix increment operator
|
||||
node_iterator &operator++() {
|
||||
// TODO: check node != nullptr
|
||||
this->node = this->node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Prefix decrement operator
|
||||
node_iterator &operator--() {
|
||||
// TODO: check node != nullptr
|
||||
this->node = this->node->previous;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/// Reverse bidirectional doubly linked list iterator
|
||||
template <class INode>
|
||||
class reverse_node_iterator : public node_iterator_base<INode> {
|
||||
public:
|
||||
reverse_node_iterator(INode *node) : node_iterator_base<INode>(node) {}
|
||||
|
||||
using difference_type = long;
|
||||
using value_type = INode;
|
||||
using pointer = INode *;
|
||||
using reference = INode &;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
/// Prefix increment operator
|
||||
reverse_node_iterator &operator++() {
|
||||
// TODO: check node != nullptr
|
||||
this->node = this->node->previous;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Prefix decrement operator
|
||||
reverse_node_iterator &operator--() {
|
||||
// TODO: check node != nullptr
|
||||
this->node = this->node->next;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
using iterator = node_iterator<Node>;
|
||||
using const_iterator = node_iterator<const Node>;
|
||||
using reverse_iterator = reverse_node_iterator<Node>;
|
||||
using const_reverse_iterator = reverse_node_iterator<const Node>;
|
||||
|
||||
/**
|
||||
* @brief Append a node to a linked list.
|
||||
*
|
||||
* @param node
|
||||
* A pointer to the node to be appended.
|
||||
*/
|
||||
void append(Node *node) {
|
||||
if (first == nullptr)
|
||||
first = node;
|
||||
node->previous = last;
|
||||
if (node->previous != nullptr)
|
||||
node->previous->next = node;
|
||||
last = node;
|
||||
node->next = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append a node to a linked list.
|
||||
*
|
||||
* @param node
|
||||
* A reference to the node to be appended.
|
||||
*/
|
||||
void append(Node &node) { append(&node); }
|
||||
|
||||
/**
|
||||
* @brief Insert a node before another node.
|
||||
*
|
||||
* @param toBeInserted
|
||||
* The new node to be inserted.
|
||||
* @param before
|
||||
* The node to insert the new node before. It must be in the list
|
||||
* already.
|
||||
*/
|
||||
void insertBefore(Node *toBeInserted, Node *before) {
|
||||
if (before == first)
|
||||
first = toBeInserted;
|
||||
else
|
||||
before->previous->next = toBeInserted;
|
||||
toBeInserted->previous = before->previous;
|
||||
toBeInserted->next = before;
|
||||
before->previous = toBeInserted;
|
||||
}
|
||||
|
||||
/// @see insertBefore(Node *, Node *)
|
||||
void insertBefore(Node &toBeInserted, Node &before) {
|
||||
insertBefore(&toBeInserted, &before);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a new node at the correct location into a sorted list.
|
||||
*
|
||||
* @param node
|
||||
* The new node to be inserted.
|
||||
* @param cmp
|
||||
* The function to order the nodes.
|
||||
* @tparam Compare
|
||||
* A functor that compares two Nodes and returns a boolean.
|
||||
*/
|
||||
template <class Compare>
|
||||
void insertSorted(Node *node, Compare cmp) {
|
||||
iterator it = this->begin();
|
||||
iterator end = this->end();
|
||||
while (it != end) {
|
||||
if (cmp(*node, *it)) {
|
||||
insertBefore(*node, *it);
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
append(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a new node at the correct location into a sorted list,
|
||||
* using `operator<`.
|
||||
*
|
||||
* @param node
|
||||
* The new node to be inserted.
|
||||
*/
|
||||
void insertSorted(Node *node) {
|
||||
insertSorted(node, [](Node &lhs, Node &rhs) { return lhs < rhs; });
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a node from the linked list.
|
||||
*
|
||||
* @param node
|
||||
* A pointer to the node to be removed.
|
||||
*/
|
||||
void remove(Node *node) {
|
||||
if (node->previous != nullptr)
|
||||
node->previous->next = node->next;
|
||||
if (node == last)
|
||||
last = node->previous;
|
||||
if (node->next != nullptr)
|
||||
node->next->previous = node->previous;
|
||||
if (node == first)
|
||||
first = node->next;
|
||||
node->previous = nullptr;
|
||||
node->next = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove a node from the linked list.
|
||||
*
|
||||
* @param node
|
||||
* A reference to the node to be removed.
|
||||
*/
|
||||
void remove(Node &node) { remove(&node); }
|
||||
|
||||
/**
|
||||
* @brief Move down the given node in the linked list.
|
||||
*
|
||||
* For example: moving down node `C`:
|
||||
* ```
|
||||
* Before: ... → A → B → C → D → ...
|
||||
* After: ... → A → C → B → D → ...
|
||||
* ```
|
||||
* @param node
|
||||
* A pointer to the node to be moved down.
|
||||
*/
|
||||
void moveDown(Node *node) {
|
||||
Node *nodeB = node->previous;
|
||||
if (nodeB == nullptr) // Can't move first node further down
|
||||
return;
|
||||
Node *nodeA = nodeB->previous;
|
||||
Node *nodeD = node->next;
|
||||
|
||||
if (nodeA != nullptr)
|
||||
nodeA->next = node;
|
||||
else
|
||||
first = node;
|
||||
nodeB->next = nodeD;
|
||||
nodeB->previous = node;
|
||||
node->next = nodeB;
|
||||
node->previous = nodeA;
|
||||
if (nodeD != nullptr)
|
||||
nodeD->previous = nodeB;
|
||||
else
|
||||
last = nodeB;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move down the given node in the linked list.
|
||||
*
|
||||
* For example: moving down node `C`:
|
||||
* ```
|
||||
* Before: ... → A → B → C → D → ...
|
||||
* After: ... → A → C → B → D → ...
|
||||
* ```
|
||||
* @param node
|
||||
* A reference to the node to be moved down.
|
||||
*/
|
||||
void moveDown(Node &node) { moveDown(&node); }
|
||||
|
||||
/**
|
||||
* @brief Check if the linked list could contain the given node.
|
||||
*
|
||||
* @retval true
|
||||
* The given node is part of some linked list or it is the first
|
||||
* node of the given linked list.
|
||||
* It could be that the node is part of a different linked list
|
||||
* if it was ever added to a different list.
|
||||
* However, **if this function returns true and the node was never
|
||||
* added to another linked list, it means that this linked list
|
||||
* contains the given node**.
|
||||
* @retval false
|
||||
* The given node is not part of any linked list, or it is the
|
||||
* only element of a different linked list.
|
||||
*/
|
||||
bool couldContain(const Node *node) const {
|
||||
return node && (node == first || node->next != nullptr ||
|
||||
node->previous != nullptr);
|
||||
}
|
||||
|
||||
/// @copydoc DoublyLinkedList::couldContain(const Node *) const
|
||||
bool couldContain(const Node &node) const { return couldContain(&node); }
|
||||
|
||||
iterator begin() { return {first}; }
|
||||
iterator end() { return {nullptr}; }
|
||||
|
||||
const_iterator begin() const { return {first}; }
|
||||
const_iterator end() const { return {nullptr}; }
|
||||
|
||||
reverse_iterator rbegin() { return {last}; }
|
||||
reverse_iterator rend() { return {nullptr}; }
|
||||
|
||||
const_reverse_iterator rbegin() const { return {last}; }
|
||||
const_reverse_iterator rend() const { return {nullptr}; }
|
||||
|
||||
/// Get a pointer to the first node.
|
||||
Node *getFirst() const { return first; }
|
||||
/// Get a pointer to the last node.
|
||||
Node *getLast() const { return last; }
|
||||
|
||||
private:
|
||||
Node *first = nullptr;
|
||||
Node *last = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that can be inherited from to allow inserting into a
|
||||
* DoublyLinkedList.
|
||||
* @tparam Node
|
||||
* The type of the nodes of the list.
|
||||
*/
|
||||
template <class Node>
|
||||
class DoublyLinkable {
|
||||
protected:
|
||||
friend class DoublyLinkedList<Node>;
|
||||
Node *next = nullptr;
|
||||
Node *previous = nullptr;
|
||||
virtual ~DoublyLinkable() = default;
|
||||
|
||||
DoublyLinkable() = default;
|
||||
DoublyLinkable(const DoublyLinkable &) {
|
||||
// Don't copy the pointers
|
||||
}
|
||||
DoublyLinkable &operator=(const DoublyLinkable &) {
|
||||
// Don't copy the pointers
|
||||
return *this;
|
||||
}
|
||||
DoublyLinkable(DoublyLinkable &&) {
|
||||
// Don't swap the pointers
|
||||
}
|
||||
DoublyLinkable &operator=(DoublyLinkable &&) {
|
||||
// Don't swap the pointers
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Containers/CRTP.hpp>
|
||||
#include <AH/Containers/LinkedList.hpp>
|
||||
#include <AH/Error/Error.hpp>
|
||||
#include <AH/STL/type_traits>
|
||||
#include <AH/STL/utility> // std::forward
|
||||
#include <AH/Settings/SettingsWrapper.hpp>
|
||||
#include <stddef.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief A super class for object that have to be updated regularly.
|
||||
*
|
||||
* All instances of this class are kept in a linked list, so it's easy to
|
||||
* iterate over all of them to update them.
|
||||
*
|
||||
* This version uses static polymorphism using the Curiously Recurring Template
|
||||
* Pattern. This requires less virtual function calls.
|
||||
* (Only the destructor is virtual.)
|
||||
*
|
||||
* @nosubgrouping
|
||||
*/
|
||||
template <class Derived>
|
||||
class UpdatableCRTP : public DoublyLinkable<Derived> {
|
||||
|
||||
public:
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
|
||||
// When a Derived instance is constructed, the base class constructor
|
||||
// UpdatableCRTP is called first. Because the Derived constructor hasn't
|
||||
// been run yet, the dynamic type is just Updatable, not yet Derived.
|
||||
// The undefined behavior sanitizer checks this dynamic type when the this
|
||||
// pointer is casted to Derived using the CRTP macro, and thus causes an
|
||||
// error.
|
||||
// The constructor only casts and stores the pointer, it doesn't dereference
|
||||
// it to call any of Derived methods, so I don't think that it's undefined
|
||||
// behavior (and I don't know of a better way to do this).
|
||||
// Also see https://stackoverflow.com/q/61061051/6356744
|
||||
|
||||
protected:
|
||||
/// Constructor: create an Updatable and add it to the linked list of
|
||||
/// instances.
|
||||
UpdatableCRTP() __attribute__((no_sanitize("undefined"))) {
|
||||
updatables.append(CRTP(Derived));
|
||||
}
|
||||
|
||||
UpdatableCRTP(const UpdatableCRTP &)
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
: DoublyLinkable<Derived>() {
|
||||
updatables.append(CRTP(Derived));
|
||||
}
|
||||
UpdatableCRTP &operator=(const UpdatableCRTP &) { return *this; }
|
||||
|
||||
UpdatableCRTP(UpdatableCRTP &&) __attribute__((no_sanitize("undefined"))) {
|
||||
updatables.append(CRTP(Derived));
|
||||
}
|
||||
UpdatableCRTP &operator=(UpdatableCRTP &&) { return *this; }
|
||||
|
||||
public:
|
||||
/// Destructor: remove the updatable from the linked list of instances.
|
||||
virtual ~UpdatableCRTP() __attribute__((no_sanitize("undefined"))) {
|
||||
if (updatables.couldContain(CRTP(Derived)))
|
||||
updatables.remove(CRTP(Derived));
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// @name Main initialization and updating methods
|
||||
/// @{
|
||||
|
||||
template <class... Args>
|
||||
static void __attribute__((always_inline))
|
||||
applyToAll(void (Derived::*method)(Args...), Args... args) {
|
||||
for (auto &el : updatables)
|
||||
(el.*method)(args...);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// @name Enabling and disabling updatables
|
||||
/// @{
|
||||
|
||||
/// Enable this updatable: insert it into the linked list of instances,
|
||||
/// so it gets updated automatically
|
||||
void enable() {
|
||||
if (isEnabled()) {
|
||||
ERROR(F("Error: This element is already enabled."), 0x1212);
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
updatables.append(CRTP(Derived));
|
||||
}
|
||||
|
||||
/// Disable this updatable: remove it from the linked list of instances,
|
||||
/// so it no longer gets updated automatically
|
||||
void disable() {
|
||||
if (!isEnabled()) {
|
||||
ERROR(F("Error: This element is already disabled."), 0x1213);
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
updatables.remove(CRTP(Derived));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if this updatable is enabled.
|
||||
*
|
||||
* @note Assumes that the updatable is not added to a different linked
|
||||
* list by the user.
|
||||
*/
|
||||
bool isEnabled() const {
|
||||
return updatables.couldContain(CRTP(const Derived));
|
||||
}
|
||||
|
||||
/// @copydoc enable()
|
||||
static void enable(UpdatableCRTP *element) { element->enable(); }
|
||||
/// @copydoc enable()
|
||||
static void enable(UpdatableCRTP &element) { element.enable(); }
|
||||
/// @copydoc enable()
|
||||
template <class U, size_t N>
|
||||
static void enable(U (&array)[N]) {
|
||||
for (U &el : array)
|
||||
enable(el);
|
||||
}
|
||||
|
||||
/// @copydoc disable()
|
||||
static void disable(UpdatableCRTP *element) { element->disable(); }
|
||||
/// @copydoc disable()
|
||||
static void disable(UpdatableCRTP &element) { element.disable(); }
|
||||
/// @copydoc disable()
|
||||
template <class U, size_t N>
|
||||
static void disable(U (&array)[N]) {
|
||||
for (U &el : array)
|
||||
disable(el);
|
||||
}
|
||||
|
||||
/// Move down this element in the list.
|
||||
void moveDown() { updatables.moveDown(CRTP(Derived)); }
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
static DoublyLinkedList<Derived> updatables;
|
||||
};
|
||||
|
||||
template <class Derived>
|
||||
DoublyLinkedList<Derived> UpdatableCRTP<Derived>::updatables;
|
||||
|
||||
struct NormalUpdatable {};
|
||||
|
||||
/**
|
||||
* @brief A super class for object that have to be updated regularly.
|
||||
*
|
||||
* All instances of this class are kept in a linked list, so it's easy to
|
||||
* iterate over all of them to update them.
|
||||
*
|
||||
* @nosubgrouping
|
||||
*/
|
||||
template <class T = NormalUpdatable>
|
||||
class Updatable : public UpdatableCRTP<Updatable<T>> {
|
||||
public:
|
||||
/// @name Main initialization and updating methods
|
||||
/// @{
|
||||
|
||||
/// Initialize this updatable.
|
||||
virtual void begin() = 0;
|
||||
|
||||
/// Update this updatable.
|
||||
virtual void update() = 0;
|
||||
|
||||
/// Begin all enabled instances of this class
|
||||
/// @see begin()
|
||||
static void beginAll() { Updatable::applyToAll(&Updatable::begin); }
|
||||
|
||||
/// Update all enabled instances of this class
|
||||
/// @see update()
|
||||
static void updateAll() { Updatable::applyToAll(&Updatable::update); }
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#include "Debug.hpp"
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
#pragma message("Debugging enabled on output " DEBUG_STR(DEBUG_OUT))
|
||||
|
||||
#ifndef ARDUINO
|
||||
BEGIN_AH_NAMESPACE
|
||||
const decltype(std::chrono::high_resolution_clock::now()) start_time =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
END_AH_NAMESPACE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
BEGIN_AH_NAMESPACE
|
||||
std::mutex debugmutex;
|
||||
END_AH_NAMESPACE
|
||||
#elif defined(ARDUINO_ARCH_MBED)
|
||||
BEGIN_AH_NAMESPACE
|
||||
rtos::Mutex debugmutex;
|
||||
END_AH_NAMESPACE
|
||||
#endif
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
#pragma once
|
||||
|
||||
/// @file
|
||||
|
||||
#include <AH/PrintStream/PrintStream.hpp>
|
||||
#include <AH/Settings/SettingsWrapper.hpp>
|
||||
|
||||
#ifndef FLUSH_ON_EVERY_DEBUG_STATEMENT
|
||||
#if !(defined(ESP32) || defined(ESP8266))
|
||||
|
||||
/// Should the output stream be flushed after each debug statement?
|
||||
/// Enabling this feature can slow things down significantly, and is not
|
||||
/// supported on ESP32 / ESP8266.
|
||||
///
|
||||
/// @todo I should probably use Streams instead of Prints, so Espressif boards
|
||||
/// can flush as well.
|
||||
#define FLUSH_ON_EVERY_DEBUG_STATEMENT 0
|
||||
|
||||
#else
|
||||
|
||||
#define FLUSH_ON_EVERY_DEBUG_STATEMENT 0
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <mutex>
|
||||
#elif defined(ARDUINO_ARCH_MBED)
|
||||
#include <mutex>
|
||||
#include <rtos/Mutex.h>
|
||||
#endif
|
||||
|
||||
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// Uncomment this line to override Arduino debug output
|
||||
// #define DEBUG_OUT Serial
|
||||
|
||||
#else
|
||||
|
||||
// Uncomment this line to override PC tests debug output
|
||||
// #define DEBUG_OUT std::cout
|
||||
|
||||
#endif
|
||||
|
||||
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
#if FLUSH_ON_EVERY_DEBUG_STATEMENT
|
||||
#define DEBUG_ENDL endl
|
||||
#else
|
||||
#define DEBUG_ENDL "\r\n"
|
||||
#endif
|
||||
|
||||
#if (defined(ESP32) || defined(ESP8266)) && FLUSH_ON_EVERY_DEBUG_STATEMENT
|
||||
#error "ESP32 and ESP8266 don't support flushing `Print` objects"
|
||||
#endif
|
||||
|
||||
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
#define DEBUG_STR_HELPER(x) #x
|
||||
#define DEBUG_STR(x) DEBUG_STR_HELPER(x)
|
||||
|
||||
#define DEBUG_FUNC_LOCATION \
|
||||
'[' << __PRETTY_FUNCTION__ << F(" @ line " DEBUG_STR(__LINE__) "]:\t")
|
||||
#define DEBUG_LOCATION "[" __FILE__ ":" DEBUG_STR(__LINE__) "]:\t"
|
||||
|
||||
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
#if defined(ESP32)
|
||||
#define DEBUG_LOCK_MUTEX std::lock_guard<std::mutex> lock(AH::debugmutex);
|
||||
BEGIN_AH_NAMESPACE
|
||||
extern std::mutex debugmutex;
|
||||
END_AH_NAMESPACE
|
||||
#elif defined(ARDUINO_ARCH_MBED)
|
||||
#define DEBUG_LOCK_MUTEX std::lock_guard<rtos::Mutex> lock(AH::debugmutex);
|
||||
BEGIN_AH_NAMESPACE
|
||||
extern rtos::Mutex debugmutex;
|
||||
END_AH_NAMESPACE
|
||||
#else
|
||||
#define DEBUG_LOCK_MUTEX
|
||||
#endif
|
||||
|
||||
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/// Macro for printing an expression as a string, followed by its value.
|
||||
/// The expression string is saved in PROGMEM using the `F(...)` macro.
|
||||
/// @ingroup AH_Debug
|
||||
#define NAMEDVALUE(x) F(DEBUG_STR(x) " = ") << x
|
||||
|
||||
#ifdef DEBUG_OUT // Debugging enabled ==========================================
|
||||
|
||||
/// Print an expression to the debug output if debugging is enabled.
|
||||
/// @ingroup AH_Debug
|
||||
#define DEBUG(x) \
|
||||
do { \
|
||||
DEBUG_LOCK_MUTEX \
|
||||
DEBUG_OUT << x << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
||||
/// Print an expression and its location (file and line number) to the debug
|
||||
/// output if debugging is enabled.
|
||||
/// The location is saved in PROGMEM using the `F(...)` macro.
|
||||
/// @ingroup AH_Debug
|
||||
#define DEBUGREF(x) \
|
||||
do { \
|
||||
DEBUG_LOCK_MUTEX \
|
||||
DEBUG_OUT << F(DEBUG_LOCATION) << x << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
||||
/// Print an expression and its function (function name and line number) to the
|
||||
/// debug output if debugging is enabled.
|
||||
/// The function name is saved in RAM.
|
||||
/// @ingroup AH_Debug
|
||||
#define DEBUGFN(x) \
|
||||
do { \
|
||||
DEBUG_LOCK_MUTEX \
|
||||
DEBUG_OUT << DEBUG_FUNC_LOCATION << x << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
/// Print an expression and the time since startup to the debug output if
|
||||
/// debugging is enabled.
|
||||
/// Format: `[hours:minutes:seconds.milliseconds]`
|
||||
/// @ingroup AH_Debug
|
||||
#define DEBUGTIME(x) \
|
||||
do { \
|
||||
DEBUG_LOCK_MUTEX \
|
||||
unsigned long t = millis(); \
|
||||
unsigned long h = t / (60UL * 60 * 1000); \
|
||||
unsigned long m = (t / (60UL * 1000)) % 60; \
|
||||
unsigned long s = (t / (1000UL)) % 60; \
|
||||
unsigned long ms = t % 1000; \
|
||||
const char *ms_zeros = ms > 99 ? "" : (ms > 9 ? "0" : "00"); \
|
||||
DEBUG_OUT << '[' << h << ':' << m << ':' << s << '.' << ms_zeros << ms \
|
||||
<< "]:\t" << x << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
||||
#else // !ARDUINO
|
||||
|
||||
#include <chrono>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
extern const decltype(std::chrono::high_resolution_clock::now()) start_time;
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#define DEBUGTIME(x) \
|
||||
do { \
|
||||
USING_AH_NAMESPACE; \
|
||||
using namespace std::chrono; \
|
||||
auto now = high_resolution_clock::now(); \
|
||||
unsigned long t = \
|
||||
duration_cast<milliseconds>(now - start_time).count(); \
|
||||
unsigned long h = t / (60UL * 60 * 1000); \
|
||||
unsigned long m = (t / (60UL * 1000)) % 60; \
|
||||
unsigned long s = (t / (1000UL)) % 60; \
|
||||
unsigned long ms = t % 1000; \
|
||||
const char *ms_zeros = ms > 99 ? "" : (ms > 9 ? "0" : "00"); \
|
||||
DEBUG_OUT << '[' << h << ':' << m << ':' << s << '.' << ms_zeros << ms \
|
||||
<< "]:\t" << x << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#include "DebugVal.hpp"
|
||||
|
||||
/// Print multiple expressions and their values to the debug output if debugging
|
||||
/// is enabled.
|
||||
/// For example, `DEBUGVAL(1 + 1, digitalRead(2))` could print `1 + 1 = 2,
|
||||
/// digitalRead(2) = 0`.
|
||||
/// A maximum of 10 expressions is supported.
|
||||
/// The expression strings are saved in PROGMEM using the `F(...)` macro.
|
||||
/// @ingroup AH_Debug
|
||||
#define DEBUGVAL(...) DEBUGVALN(COUNT(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#else // Debugging disabled ====================================================
|
||||
|
||||
#define DEBUG(x) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUGREF(x) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUGFN(x) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUGTIME(x) \
|
||||
do { \
|
||||
} while (0)
|
||||
#define DEBUGVAL(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#define COUNT(...) COUNT_HELPER(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
#define COUNT_HELPER(N1, N2, N3, N4, N5, N6, N7, N8, N9, N10, N, ...) N
|
||||
|
||||
#define DEBUGVALN(N) DEBUGVALN_HELPER(N)
|
||||
#define DEBUGVALN_HELPER(N) DEBUGVAL##N
|
||||
|
||||
#define DEBUGVAL10(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL9(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL9(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL8(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL8(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL7(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL7(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL6(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL6(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL5(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL5(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL4(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL4(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL3(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL3(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL2(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL2(x, ...) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << ", "; \
|
||||
DEBUGVAL1(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUGVAL1(x) \
|
||||
do { \
|
||||
DEBUG_OUT << NAMEDVALUE(x) << DEBUG_ENDL; \
|
||||
} while (0)
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
/// @file
|
||||
|
||||
#include <AH/Debug/Debug.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// Blinks the built-in LED and loops forever on fatal error.
|
||||
extern void fatalErrorExit() __attribute__((noreturn));
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#ifdef FATAL_ERRORS
|
||||
|
||||
#define ERROR(msg, errc) \
|
||||
do { \
|
||||
USING_AH_NAMESPACE; \
|
||||
DEBUGFN(msg << " (0x" << hex << uppercase << errc << dec \
|
||||
<< nouppercase << ')'); \
|
||||
fatalErrorExit(); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define ERROR(msg, errc) \
|
||||
do { \
|
||||
DEBUGFN(msg << " (0x" << hex << uppercase << errc << dec \
|
||||
<< nouppercase << ')'); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define FATAL_ERROR(msg, errc) \
|
||||
do { \
|
||||
USING_AH_NAMESPACE; \
|
||||
DEBUGFN(F("Fatal Error: ") << msg << " (0x" << hex << uppercase \
|
||||
<< errc << dec << nouppercase << ')'); \
|
||||
fatalErrorExit(); \
|
||||
} while (0)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "Error.hpp"
|
||||
#include <platform/pico_shim.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
void fatalErrorExit() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
while (1) {
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
sleep_ms(50);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
sleep_ms(50);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
sleep_ms(50);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
sleep_ms(850);
|
||||
}
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <AH/STL/limits>
|
||||
#include <AH/STL/type_traits>
|
||||
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief Exponential moving average filter.
|
||||
*
|
||||
* Fast integer EMA implementation where the weight factor is a power of two.
|
||||
*
|
||||
* Difference equation: @f$ y[n] = \alpha·x[n]+(1-\alpha)·y[n-1] @f$
|
||||
* where @f$ \alpha = \left(\frac{1}{2}\right)^{K} @f$, @f$ x @f$ is the
|
||||
* input sequence, and @f$ y @f$ is the output sequence.
|
||||
*
|
||||
* [An in-depth explanation of the EMA filter](https://tttapa.github.io/Pages/Mathematics/Systems-and-Control-Theory/Digital-filters/Exponential%20Moving%20Average/)
|
||||
*
|
||||
* @tparam K
|
||||
* The amount of bits to shift by. This determines the location
|
||||
* of the pole in the EMA transfer function, and therefore the
|
||||
* cut-off frequency.
|
||||
* The higher this number, the more filtering takes place.
|
||||
* The pole location is @f$ 1 - 2^{-K} @f$.
|
||||
* @tparam input_t
|
||||
* The integer type to use for the input and output of the filter.
|
||||
* Can be signed or unsigned.
|
||||
* @tparam state_t
|
||||
* The unsigned integer type to use for the internal state of the
|
||||
* filter. A fixed-point representation with @f$ K @f$ fractional
|
||||
* bits is used, so this type should be at least @f$ M + K @f$ bits
|
||||
* wide, where @f$ M @f$ is the maximum number of bits of the input.
|
||||
*
|
||||
* Some examples of different combinations of template parameters:
|
||||
*
|
||||
* 1. Filtering the result of `analogRead`: analogRead returns an integer
|
||||
* between 0 and 1023, which can be represented using 10 bits, so
|
||||
* @f$ M = 10 @f$. If `input_t` and `output_t` are both `uint16_t`,
|
||||
* the maximum shift factor `K` is @f$ 16 - M = 6 @f$. If `state_t`
|
||||
* is increased to `uint32_t`, the maximum shift factor `K` is
|
||||
* @f$ 32 - M = 22 @f$.
|
||||
* 2. Filtering a signed integer between -32768 and 32767: this can be
|
||||
* represented using a 16-bit signed integer, so `input_t` is `int16_t`,
|
||||
* and @f$ M = 16 @f$. (2¹⁵ = 32768)
|
||||
* Let's say the shift factor `K` is 1, then the minimum width of
|
||||
* `state_t` should be @f$ M + K = 17 @f$ bits, so `uint32_t` would be
|
||||
* a sensible choice.
|
||||
*
|
||||
* @ingroup AH_Filters
|
||||
*/
|
||||
template <uint8_t K,
|
||||
class input_t = uint_fast16_t,
|
||||
class state_t = typename std::make_unsigned<input_t>::type>
|
||||
class EMA {
|
||||
public:
|
||||
/// Constructor: initialize filter to zero or optional given value.
|
||||
EMA(input_t initial = input_t{0}) { reset(initial); }
|
||||
|
||||
/**
|
||||
* @brief Reset the filter to the given value.
|
||||
*
|
||||
* @param value
|
||||
* The value to reset the filter state to.
|
||||
*/
|
||||
void reset(input_t value = input_t(0)) {
|
||||
state_t value_s = static_cast<state_t>(value);
|
||||
state = zero + (value_s << K) - value_s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Filter the input: Given @f$ x[n] @f$, calculate @f$ y[n] @f$.
|
||||
*
|
||||
* @param input
|
||||
* The new raw input value.
|
||||
* @return The new filtered output value.
|
||||
*/
|
||||
input_t filter(input_t input) {
|
||||
state += static_cast<state_t>(input);
|
||||
state_t output = (state + half) >> K;
|
||||
output -= zero >> K;
|
||||
state -= output;
|
||||
return static_cast<input_t>(output);
|
||||
}
|
||||
|
||||
/// @copydoc EMA::filter(input_t)
|
||||
input_t operator()(input_t input) {
|
||||
return filter(input);
|
||||
}
|
||||
|
||||
constexpr static state_t
|
||||
max_state = std::numeric_limits<state_t>::max(),
|
||||
half_state = max_state / 2 + 1,
|
||||
zero = std::is_unsigned<input_t>::value ? state_t{0} : half_state,
|
||||
half = K > 0 ? state_t{1} << (K - 1) : state_t{0};
|
||||
|
||||
static_assert(std::is_unsigned<state_t>::value,
|
||||
"state type should be unsigned");
|
||||
|
||||
static_assert(max_state >= std::numeric_limits<input_t>::max(),
|
||||
"state type cannot be narrower than input type");
|
||||
|
||||
/// Verify the input range to make sure it's compatible with the shift
|
||||
/// factor and the width of the state type.
|
||||
///
|
||||
/// Examples:
|
||||
/// ~~~cpp
|
||||
/// EMA<5, int_fast16_t, uint_fast16_t> filter;
|
||||
/// static_assert(filter.supports_range(-1024, 1023),
|
||||
/// "use a wider state or input type, or a smaller shift factor");
|
||||
/// ~~~
|
||||
/// ~~~cpp
|
||||
/// EMA<5, uint_fast16_t, uint_fast16_t> filter;
|
||||
/// static_assert(filter.supports_range(0u, 2047u),
|
||||
/// "use a wider state or input type, or a smaller shift factor");
|
||||
/// ~~~
|
||||
template <class T>
|
||||
constexpr static bool supports_range(T min, T max) {
|
||||
using sstate_t = typename std::make_signed<state_t>::type;
|
||||
return min <= max &&
|
||||
min >= std::numeric_limits<input_t>::min() &&
|
||||
max <= std::numeric_limits<input_t>::max() &&
|
||||
(std::is_unsigned<input_t>::value
|
||||
? state_t(max) <= (max_state >> K)
|
||||
: min >= -static_cast<sstate_t>(max_state >> (K + 1)) - 1 &&
|
||||
max <= static_cast<sstate_t>(max_state >> (K + 1)));
|
||||
}
|
||||
|
||||
private:
|
||||
state_t state;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* @brief A class for single-pole infinite impulse response filters
|
||||
* or exponential moving average filters.
|
||||
*
|
||||
* This version uses floating point maths.
|
||||
*
|
||||
* Difference equation: @f$ y[n] = \alpha·x[n]+(1-\alpha)·y[n-1] @f$
|
||||
* @f$ x @f$ is the input sequence, and @f$ y @f$ is the output sequence.
|
||||
*
|
||||
* [An in-depth explanation of the EMA filter]
|
||||
* (https://tttapa.github.io/Pages/Mathematics/Systems-and-Control-Theory/Digital-filters/Exponential%20Moving%20Average/)
|
||||
*
|
||||
* @ingroup AH_Filters
|
||||
*/
|
||||
class EMA_f {
|
||||
public:
|
||||
/**
|
||||
* @brief Create an exponential moving average filter with a pole at the
|
||||
* given location.
|
||||
*
|
||||
* @param pole
|
||||
* The pole of the filter (@f$1-\alpha@f$).
|
||||
* Should be a value in the range
|
||||
* @f$ \left[0,1\right) @f$.
|
||||
* Zero means no filtering, and closer to one means more filtering.
|
||||
*/
|
||||
EMA_f(float pole) : alpha(1 - pole) {}
|
||||
|
||||
/**
|
||||
* @brief Filter the input: Given @f$ x[n] @f$, calculate @f$ y[n] @f$.
|
||||
*
|
||||
* @param value
|
||||
* The new raw input value.
|
||||
* @return The new filtered output value.
|
||||
*/
|
||||
float filter(float value) {
|
||||
filtered += (value - filtered) * alpha;
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/// @copydoc filter(float)
|
||||
float operator()(float value) { return filter(value); }
|
||||
|
||||
private:
|
||||
float alpha;
|
||||
float filtered = 0;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// @addtogroup AH_Filters
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief A class for applying hysteresis to a given input.
|
||||
*
|
||||
* This reduces the noise by decreasing the resolution, and it prevents flipping
|
||||
* back and forth between two values.
|
||||
*
|
||||
* <b>An example for `BITS` = 7 and an input from 0 to 1023</b>
|
||||
* ```
|
||||
* 7 ┌───◄───┬───
|
||||
* o 6 ┌───◄───┼───►───┘
|
||||
* u 5 ┌───◄───┼───►───┘
|
||||
* t 4 ┌───◄───┼───►───┘
|
||||
* p 3 ┌───◄───┼───►───┘
|
||||
* u 2 ┌───◄───┼───►───┘
|
||||
* t 1 ┌───◄───┼───►───┘
|
||||
* 0 ────┴───►───┘
|
||||
* 0 128 256 384 512 640 768 896 1023
|
||||
* i n p u t
|
||||
* ```
|
||||
*
|
||||
* @tparam BITS
|
||||
* The number of bits to decrease in resolution.
|
||||
* Increasing this number will result in a decrease in fluctuations.
|
||||
*/
|
||||
template <uint8_t Bits, class T_in = uint16_t, class T_out = uint8_t>
|
||||
class Hysteresis {
|
||||
public:
|
||||
/**
|
||||
* @brief Update the hysteresis output with a new input value.
|
||||
*
|
||||
* @param inputLevel
|
||||
* The input to calculate the output level from.
|
||||
* @retval true
|
||||
* The output level has changed.
|
||||
* @retval false
|
||||
* The output level is still the same.
|
||||
*/
|
||||
bool update(T_in inputLevel) {
|
||||
T_in prevLevelFull = (T_in(prevLevel) << Bits) | offset;
|
||||
T_in lowerbound = prevLevel > 0 ? prevLevelFull - margin : 0;
|
||||
T_in upperbound = prevLevel < max_out ? prevLevelFull + margin : max_in;
|
||||
if (inputLevel < lowerbound || inputLevel > upperbound) {
|
||||
setValue(inputLevel);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current output level.
|
||||
*
|
||||
* @return The output level.
|
||||
*/
|
||||
T_out getValue() const { return prevLevel; }
|
||||
|
||||
/**
|
||||
* @brief Forcefully update the internal state to the given level.
|
||||
*/
|
||||
void setValue(T_in inputLevel) { prevLevel = inputLevel >> Bits; }
|
||||
|
||||
private:
|
||||
T_out prevLevel = 0;
|
||||
constexpr static T_in margin = (1ul << Bits) - 1ul;
|
||||
constexpr static T_in offset = Bits >= 1 ? 1ul << (Bits - 1) : 0;
|
||||
constexpr static T_in max_in = static_cast<T_in>(-1);
|
||||
constexpr static T_out max_out = static_cast<T_out>(max_in >> Bits);
|
||||
static_assert(max_in > 0, "Error: only unsigned types are supported");
|
||||
};
|
||||
|
||||
template <class T_in, class T_out>
|
||||
class Hysteresis<0, T_in, T_out> {
|
||||
public:
|
||||
bool update(T_in inputLevel) {
|
||||
bool changed = inputLevel != prevLevel;
|
||||
prevLevel = inputLevel;
|
||||
return changed;
|
||||
}
|
||||
|
||||
T_out getValue() const { return prevLevel; }
|
||||
void setValue(T_in inputLevel) { prevLevel = inputLevel; }
|
||||
|
||||
private:
|
||||
T_in prevLevel = 0;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
// RP2350 has a 12-bit SAR ADC
|
||||
#ifndef ADC_RESOLUTION
|
||||
#define ADC_RESOLUTION 12
|
||||
#endif
|
||||
#define HAS_ANALOG_READ_RESOLUTION 1
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
// pico-sdk version: simple typedefs, no FunctionTraits introspection
|
||||
|
||||
#include <AH/Hardware/Hardware-Types.hpp>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
using ArduinoPin_t = uint8_t;
|
||||
using PinStatus_t = uint8_t;
|
||||
using PinMode_t = uint8_t;
|
||||
using BitOrder_t = uint8_t;
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
template <class T>
|
||||
constexpr ArduinoPin_t arduino_pin_cast(T t) {
|
||||
return static_cast<ArduinoPin_t>(t);
|
||||
}
|
||||
constexpr ArduinoPin_t arduino_pin_cast(pin_t t) { return t.pin; }
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#include "Button.hpp"
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
Button::Button(pin_t pin) : pin(pin) {}
|
||||
|
||||
void Button::begin() { ExtIO::pinMode(pin, INPUT_PULLUP); }
|
||||
|
||||
void Button::invert() { state.invert = true; }
|
||||
|
||||
Button::State Button::update() {
|
||||
// Read pin state and current time
|
||||
bool input = ExtIO::digitalRead(pin) ^ state.invert;
|
||||
unsigned long now = millis();
|
||||
// Check if enough time has elapsed after last bounce
|
||||
if (state.bouncing)
|
||||
state.bouncing = now - state.prevBounceTime <= debounceTime;
|
||||
// Shift the debounced state one bit to the left, either appending the
|
||||
// new input state if not bouncing, or repeat the old state if bouncing
|
||||
bool prevState = state.debounced & 0b01;
|
||||
bool newState = state.bouncing ? prevState : input;
|
||||
state.debounced = (prevState << 1) | newState;
|
||||
// Check if the input changed state (button pressed, released or bouncing)
|
||||
if (input != state.prevInput) {
|
||||
state.bouncing = true;
|
||||
state.prevInput = input;
|
||||
state.prevBounceTime = now;
|
||||
}
|
||||
return getState();
|
||||
}
|
||||
|
||||
Button::State Button::getState() const {
|
||||
return static_cast<State>(state.debounced);
|
||||
}
|
||||
|
||||
FlashString_t Button::getName(Button::State state) {
|
||||
switch (state) {
|
||||
case Button::Pressed: return F("Pressed");
|
||||
case Button::Released: return F("Released");
|
||||
case Button::Falling: return F("Falling");
|
||||
case Button::Rising: return F("Rising");
|
||||
default: return F("<invalid>"); // Keeps the compiler happy
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long Button::previousBounceTime() const {
|
||||
return state.prevBounceTime;
|
||||
}
|
||||
|
||||
unsigned long Button::stableTime(unsigned long now) const {
|
||||
return now - previousBounceTime();
|
||||
}
|
||||
|
||||
unsigned long Button::stableTime() const { return stableTime(millis()); }
|
||||
|
||||
void Button::setDebounceTime(unsigned long debounceTime) {
|
||||
Button::debounceTime = debounceTime;
|
||||
}
|
||||
|
||||
unsigned long Button::getDebounceTime() { return Button::debounceTime; }
|
||||
|
||||
unsigned long Button::debounceTime = BUTTON_DEBOUNCE_TIME;
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp>
|
||||
#include <AH/Settings/SettingsWrapper.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief A class for reading and debouncing buttons and switches.
|
||||
*
|
||||
* @ingroup AH_HardwareUtils
|
||||
*/
|
||||
class Button {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Button object.
|
||||
*
|
||||
* **This constructor should not be used.**
|
||||
* It is just a way to easily create arrays of buttons, and initializing
|
||||
* them later.
|
||||
*/
|
||||
Button() : pin(NO_PIN) {}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Button object.
|
||||
*
|
||||
* @param pin
|
||||
* The digital pin to read from. The internal pull-up resistor
|
||||
* will be enabled when `begin` is called.
|
||||
*/
|
||||
Button(pin_t pin);
|
||||
/// @copydoc Button(pin_t)
|
||||
Button(ArduinoPin_t pin) : Button(pin_t(pin)) {}
|
||||
|
||||
/// @brief Initialize (enable the internal pull-up resistor).
|
||||
void begin();
|
||||
|
||||
/**
|
||||
* @brief Invert the input state of this button
|
||||
* (button pressed is `HIGH` instead of `LOW`).
|
||||
*/
|
||||
void invert();
|
||||
|
||||
/// @brief An enumeration of the different states a button can be in.
|
||||
enum State {
|
||||
Pressed = 0b00, ///< Input went from low to low (0,0)
|
||||
Released = 0b11, ///< Input went from high to high (1,1)
|
||||
Falling = 0b10, ///< Input went from high to low (1,0)
|
||||
Rising = 0b01 ///< Input went from low to high (0,1)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read the button and return its new state.
|
||||
*
|
||||
* The button is debounced, the debounce time can be set in
|
||||
* Settings.hpp: #BUTTON_DEBOUNCE_TIME.
|
||||
*
|
||||
* ```
|
||||
* Debounce time: ├────┤
|
||||
*
|
||||
* Raw input:
|
||||
* HIGH ──────┐ ┌──────┐ ┌─┐ ┌─┐ ┌──────┐ ┌────────
|
||||
* LOW └──────┘ └─┘ └──────┘ └─┘ └─┘
|
||||
* ├────┤ ├────┤ ├─┼─┼────┤ ├─┼─┼────┤ ├─┼────┤
|
||||
*
|
||||
* Debounced output:
|
||||
* HIGH ──────┐ ┌──────┐ ┌──────────┐ ┌───
|
||||
* LOW └──────┘ └──────────┘ └──────┘
|
||||
*
|
||||
* States:
|
||||
* HIGH ────────────────┐ ┌─────────────────
|
||||
* LOW └──────────────────┘
|
||||
* Released Falling Pressed Rising
|
||||
* ```
|
||||
*
|
||||
* @return The state of the button, either Button::Pressed,
|
||||
* Button::Released, Button::Falling or Button::Rising.
|
||||
*/
|
||||
State update();
|
||||
|
||||
/**
|
||||
* @brief Get the state of the button, without updating it.
|
||||
* Returns the same value as the last call to @ref update.
|
||||
*
|
||||
* @return The state of the button, either Button::Pressed,
|
||||
* Button::Released, Button::Falling or Button::Rising.
|
||||
*/
|
||||
State getState() const;
|
||||
|
||||
/// @brief Return the name of the state as a string.
|
||||
static FlashString_t getName(State state);
|
||||
|
||||
/// Return the time point (in milliseconds) when the button last bounced.
|
||||
unsigned long previousBounceTime() const;
|
||||
|
||||
/// Return the time (in milliseconds) that the button has been stable for,
|
||||
/// compared to the given time point.
|
||||
unsigned long stableTime(unsigned long now) const;
|
||||
|
||||
/// Return the time (in milliseconds) that the button has been stable for.
|
||||
unsigned long stableTime() const;
|
||||
|
||||
/**
|
||||
* @brief Set the debounce time for all Button%s.
|
||||
*
|
||||
* @note This function affects **all** Button objects.
|
||||
*
|
||||
* @param debounceTime
|
||||
* The new debounce time in milliseconds.
|
||||
*/
|
||||
static void
|
||||
setDebounceTime(unsigned long debounceTime = BUTTON_DEBOUNCE_TIME);
|
||||
|
||||
/**
|
||||
* @brief Get the debounce time.
|
||||
* @return The debounce time in milliseconds.
|
||||
* @see setDebounceTime
|
||||
*/
|
||||
static unsigned long getDebounceTime();
|
||||
|
||||
private:
|
||||
pin_t pin;
|
||||
|
||||
struct InternalState {
|
||||
InternalState()
|
||||
: debounced(0b11), bouncing(true), prevInput(HIGH), invert(false),
|
||||
prevBounceTime(0) {}
|
||||
uint8_t debounced : 2;
|
||||
bool bouncing : 1;
|
||||
bool prevInput : 1;
|
||||
bool invert : 1;
|
||||
unsigned long prevBounceTime;
|
||||
} state;
|
||||
|
||||
/// Edit this in Settings.hpp
|
||||
/// @see BUTTON_DEBOUNCE_TIME
|
||||
static unsigned long debounceTime;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AH/Hardware/Hardware-Types.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief A class that reads the states of a button matrix.
|
||||
*
|
||||
* @tparam NumRows
|
||||
* The number of rows in the button matrix.
|
||||
* @tparam NumCols
|
||||
* The number of columns in the button matrix.
|
||||
*
|
||||
* @ingroup AH_HardwareUtils
|
||||
*/
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
class ButtonMatrix {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new ButtonMatrix object.
|
||||
*
|
||||
* @param rowPins
|
||||
* A list of pin numbers connected to the rows of the button
|
||||
* matrix.
|
||||
* **⚠** These pins will be driven LOW as outputs (Lo-Z).
|
||||
* @param colPins
|
||||
* A list of pin numbers connected to the columns of the button
|
||||
* matrix.
|
||||
* These pins will be used as inputs (Hi-Z), and the internal
|
||||
* pull-up resistor will be enabled.
|
||||
*/
|
||||
ButtonMatrix(const PinList<NumRows> &rowPins,
|
||||
const PinList<NumCols> &colPins);
|
||||
|
||||
/**
|
||||
* @brief Initialize (enable internal pull-up resistors on column pins).
|
||||
*/
|
||||
void begin();
|
||||
|
||||
/**
|
||||
* @brief Scan the matrix, read all button states, and call the
|
||||
* onButtonChanged callback.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* Get the state of the button in the given column and row.
|
||||
*
|
||||
* @note No bounds checking is performed.
|
||||
*/
|
||||
bool getPrevState(uint8_t col, uint8_t row);
|
||||
|
||||
/// Configure the debounce time interval. Only one button can change in each
|
||||
/// debounce interval. Time in milliseconds.
|
||||
void setDebounceTime(unsigned long debounceTime) {
|
||||
this->debounceTime = debounceTime;
|
||||
}
|
||||
/// Get the debounce time.
|
||||
unsigned long getDebounceTime() const { return debounceTime; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief The callback function that is called whenever a button changes
|
||||
* state. Implement this in the derived class.
|
||||
*
|
||||
* @param row
|
||||
* The row of the button that changed state.
|
||||
* @param col
|
||||
* The column of the button that changed state.
|
||||
* @param state
|
||||
* The new state of the button.
|
||||
*/
|
||||
void onButtonChanged(uint8_t row, uint8_t col, bool state) = delete;
|
||||
|
||||
private:
|
||||
static inline uint8_t positionToBits(uint8_t col, uint8_t row);
|
||||
static inline uint8_t bitsToIndex(uint8_t bits);
|
||||
static inline uint8_t bitsToBitmask(uint8_t bits);
|
||||
void setPrevState(uint8_t col, uint8_t row, bool state);
|
||||
|
||||
unsigned long debounceTime = BUTTON_DEBOUNCE_TIME;
|
||||
unsigned long prevRefresh = 0;
|
||||
uint8_t prevStates[(NumCols * NumRows + 7) / 8];
|
||||
|
||||
const PinList<NumRows> rowPins;
|
||||
const PinList<NumCols> colPins;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#include "ButtonMatrix.ipp" // Template implementations
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#include "ButtonMatrix.hpp"
|
||||
#include <AH/Containers/CRTP.hpp>
|
||||
#include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp>
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
ButtonMatrix<Derived, NumRows, NumCols>::ButtonMatrix(
|
||||
const PinList<NumRows> &rowPins, const PinList<NumCols> &colPins)
|
||||
: rowPins(rowPins), colPins(colPins) {
|
||||
memset(prevStates, 0xFF, sizeof(prevStates));
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
void ButtonMatrix<Derived, NumRows, NumCols>::update() {
|
||||
unsigned long now = millis();
|
||||
// only update 25 ms after previous change (crude software debounce).
|
||||
// Edit this in Settings/Settings.hpp
|
||||
if (now - prevRefresh < debounceTime)
|
||||
return;
|
||||
|
||||
for (size_t row = 0; row < NumRows; row++) { // scan through all rows
|
||||
pinMode(rowPins[row], OUTPUT); // make the current row Lo-Z 0V
|
||||
#if !defined(__AVR__) && defined(ARDUINO)
|
||||
delayMicroseconds(SELECT_LINE_DELAY);
|
||||
#endif
|
||||
for (size_t col = 0; col < NumCols; col++) { // scan through all columns
|
||||
bool state = digitalRead(colPins[col]); // read the state
|
||||
if (state != getPrevState(col, row)) {
|
||||
// if the state changed since last time
|
||||
// execute the handler
|
||||
CRTP(Derived).onButtonChanged(row, col, state);
|
||||
setPrevState(col, row, state); // remember the state
|
||||
prevRefresh = now;
|
||||
}
|
||||
}
|
||||
pinMode(rowPins[row], INPUT); // make the current row Hi-Z again
|
||||
}
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
void ButtonMatrix<Derived, NumRows, NumCols>::begin() {
|
||||
// make all columns input pins and enable
|
||||
// the internal pull-up resistors
|
||||
for (const pin_t &colPin : colPins)
|
||||
pinMode(colPin, INPUT_PULLUP);
|
||||
// make all rows Hi-Z
|
||||
for (const pin_t &rowPin : rowPins)
|
||||
pinMode(rowPin, INPUT);
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
inline uint8_t
|
||||
ButtonMatrix<Derived, NumRows, NumCols>::positionToBits(uint8_t col,
|
||||
uint8_t row) {
|
||||
// map from a 2D array of bits to a flat array of bits
|
||||
return col * NumRows + row;
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
inline uint8_t
|
||||
ButtonMatrix<Derived, NumRows, NumCols>::bitsToIndex(uint8_t bits) {
|
||||
return bits >> 3; // bits / 8
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
inline uint8_t
|
||||
ButtonMatrix<Derived, NumRows, NumCols>::bitsToBitmask(uint8_t bits) {
|
||||
return 1 << (bits & 7); // bits % 8
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
bool ButtonMatrix<Derived, NumRows, NumCols>::getPrevState(uint8_t col,
|
||||
uint8_t row) {
|
||||
uint8_t bits = positionToBits(col, row);
|
||||
return !!(prevStates[bitsToIndex(bits)] & bitsToBitmask(bits));
|
||||
}
|
||||
|
||||
template <class Derived, uint8_t NumRows, uint8_t NumCols>
|
||||
void ButtonMatrix<Derived, NumRows, NumCols>::setPrevState(uint8_t col,
|
||||
uint8_t row,
|
||||
bool state) {
|
||||
uint8_t bits = positionToBits(col, row);
|
||||
if (state)
|
||||
prevStates[bitsToIndex(bits)] |= bitsToBitmask(bits);
|
||||
else
|
||||
prevStates[bitsToIndex(bits)] &= ~bitsToBitmask(bits);
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
#include "ExtendedIOElement.hpp"
|
||||
#include <AH/Error/Error.hpp>
|
||||
#include <AH/STL/type_traits>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
ExtendedIOElement::ExtendedIOElement(pin_int_t length)
|
||||
: length(length), start(offset), end(offset + length) {
|
||||
if (end > NO_PIN)
|
||||
FATAL_ERROR(F("ExtIO ran out of pin numbers."), 0x00FF);
|
||||
offset = end;
|
||||
}
|
||||
|
||||
void ExtendedIOElement::beginAll() {
|
||||
ExtendedIOElement::applyToAll(&ExtendedIOElement::begin);
|
||||
}
|
||||
|
||||
void ExtendedIOElement::updateAllBufferedOutputs() {
|
||||
ExtendedIOElement::applyToAll(&ExtendedIOElement::updateBufferedOutputs);
|
||||
}
|
||||
|
||||
void ExtendedIOElement::updateAllBufferedInputs() {
|
||||
ExtendedIOElement::applyToAll(&ExtendedIOElement::updateBufferedInputs);
|
||||
}
|
||||
|
||||
pin_t ExtendedIOElement::pin(pin_int_t p) const {
|
||||
if (p >= length) {
|
||||
ERROR(F("Error: pin number out of range"), 0x4567);
|
||||
return end - 1;
|
||||
}
|
||||
return p + start;
|
||||
}
|
||||
|
||||
pin_t ExtendedIOElement::operator[](pin_int_t p) const { return pin(p); }
|
||||
pin_int_t ExtendedIOElement::getLength() const { return length; }
|
||||
pin_t ExtendedIOElement::getEnd() const { return end; }
|
||||
pin_t ExtendedIOElement::getStart() const { return start; }
|
||||
|
||||
DoublyLinkedList<ExtendedIOElement> &ExtendedIOElement::getAll() {
|
||||
return updatables;
|
||||
}
|
||||
|
||||
pin_t ExtendedIOElement::offset = NUM_DIGITAL_PINS + NUM_ANALOG_INPUTS;
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
|
||||
#include "ExtendedInputOutput.hpp"
|
||||
#include <AH/Containers/Updatable.hpp>
|
||||
#include <AH/Hardware/Hardware-Types.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
class ExtendedIOElement : public UpdatableCRTP<ExtendedIOElement> {
|
||||
protected:
|
||||
ExtendedIOElement(pin_int_t length);
|
||||
ExtendedIOElement(const ExtendedIOElement &) = delete;
|
||||
ExtendedIOElement &operator=(const ExtendedIOElement &) = delete;
|
||||
ExtendedIOElement(ExtendedIOElement &&) = default;
|
||||
ExtendedIOElement &operator=(ExtendedIOElement &&) = delete;
|
||||
|
||||
public:
|
||||
virtual void pinMode(pin_int_t pin, PinMode_t mode) {
|
||||
pinModeBuffered(pin, mode);
|
||||
updateBufferedOutputs();
|
||||
}
|
||||
virtual void pinModeBuffered(pin_int_t pin, PinMode_t mode) = 0;
|
||||
|
||||
virtual void digitalWrite(pin_int_t pin, PinStatus_t state) {
|
||||
digitalWriteBuffered(pin, state);
|
||||
updateBufferedOutputs();
|
||||
}
|
||||
virtual void digitalWriteBuffered(pin_int_t pin, PinStatus_t state) = 0;
|
||||
|
||||
virtual PinStatus_t digitalRead(pin_int_t pin) {
|
||||
updateBufferedInputs();
|
||||
return digitalReadBuffered(pin);
|
||||
}
|
||||
virtual PinStatus_t digitalReadBuffered(pin_int_t pin) = 0;
|
||||
|
||||
virtual void analogWrite(pin_int_t pin, analog_t val) {
|
||||
analogWriteBuffered(pin, val);
|
||||
updateBufferedOutputs();
|
||||
}
|
||||
virtual void analogWriteBuffered(pin_int_t pin, analog_t val) = 0;
|
||||
|
||||
virtual analog_t analogRead(pin_int_t pin) {
|
||||
updateBufferedInputs();
|
||||
return analogReadBuffered(pin);
|
||||
}
|
||||
virtual analog_t analogReadBuffered(pin_int_t pin) = 0;
|
||||
|
||||
virtual void begin() = 0;
|
||||
static void beginAll();
|
||||
|
||||
virtual void updateBufferedOutputs() = 0;
|
||||
static void updateAllBufferedOutputs();
|
||||
|
||||
virtual void updateBufferedInputs() = 0;
|
||||
static void updateAllBufferedInputs();
|
||||
|
||||
pin_t pin(pin_int_t pin) const;
|
||||
pin_t operator[](pin_int_t pin) const;
|
||||
pin_int_t getLength() const;
|
||||
pin_t getEnd() const;
|
||||
pin_t getStart() const;
|
||||
static DoublyLinkedList<ExtendedIOElement> &getAll();
|
||||
|
||||
private:
|
||||
const pin_int_t length;
|
||||
const pin_t start;
|
||||
const pin_t end;
|
||||
static pin_t offset;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
#include "ExtendedInputOutput.hpp"
|
||||
#include "ExtendedIOElement.hpp"
|
||||
#include <AH/Error/Error.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
namespace ExtIO {
|
||||
|
||||
template <class T>
|
||||
static bool inRange(T target, T start, T end) {
|
||||
return target >= start && target < end;
|
||||
}
|
||||
|
||||
ExtendedIOElement *getIOElementOfPinOrNull(pin_t pin) {
|
||||
for (auto &el : ExtendedIOElement::getAll())
|
||||
if (pin < el.getStart())
|
||||
break;
|
||||
else if (inRange(pin, el.getStart(), el.getEnd()))
|
||||
return ⪙
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ExtendedIOElement *getIOElementOfPin(pin_t pin) {
|
||||
auto *el = getIOElementOfPinOrNull(pin);
|
||||
if (el == nullptr)
|
||||
FATAL_ERROR(
|
||||
F("The given pin does not correspond to an Extended IO element."),
|
||||
0x8888);
|
||||
return el;
|
||||
}
|
||||
|
||||
void pinMode(pin_t pin, PinMode_t mode) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::pinMode(arduino_pin_cast(pin), mode);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->pinMode(pin - el->getStart(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(pin_t pin, PinStatus_t val) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::digitalWrite(arduino_pin_cast(pin), val);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->digitalWrite(pin - el->getStart(), val);
|
||||
}
|
||||
}
|
||||
|
||||
PinStatus_t digitalRead(pin_t pin) {
|
||||
if (pin == NO_PIN)
|
||||
return LOW;
|
||||
else if (isNativePin(pin))
|
||||
return ::digitalRead(arduino_pin_cast(pin));
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
return el->digitalRead(pin - el->getStart());
|
||||
}
|
||||
}
|
||||
|
||||
analog_t analogRead(pin_t pin) {
|
||||
if (pin == NO_PIN)
|
||||
return 0;
|
||||
else if (isNativePin(pin))
|
||||
return ::analogRead(arduino_pin_cast(pin));
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
return el->analogRead(pin - el->getStart());
|
||||
}
|
||||
}
|
||||
|
||||
void analogWrite(pin_t pin, analog_t val) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::analogWrite(arduino_pin_cast(pin), val);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->analogWrite(pin - el->getStart(), val);
|
||||
}
|
||||
}
|
||||
void analogWrite(pin_t pin, int val) { analogWrite(pin, (analog_t)val); }
|
||||
|
||||
void pinModeBuffered(pin_t pin, PinMode_t mode) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::pinMode(arduino_pin_cast(pin), mode);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->pinModeBuffered(pin - el->getStart(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWriteBuffered(pin_t pin, PinStatus_t val) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::digitalWrite(arduino_pin_cast(pin), val);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->digitalWriteBuffered(pin - el->getStart(), val);
|
||||
}
|
||||
}
|
||||
|
||||
PinStatus_t digitalReadBuffered(pin_t pin) {
|
||||
if (pin == NO_PIN)
|
||||
return LOW;
|
||||
else if (isNativePin(pin))
|
||||
return ::digitalRead(arduino_pin_cast(pin));
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
return el->digitalReadBuffered(pin - el->getStart());
|
||||
}
|
||||
}
|
||||
|
||||
analog_t analogReadBuffered(pin_t pin) {
|
||||
if (pin == NO_PIN)
|
||||
return 0;
|
||||
else if (isNativePin(pin))
|
||||
return ::analogRead(arduino_pin_cast(pin));
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
return el->analogReadBuffered(pin - el->getStart());
|
||||
}
|
||||
}
|
||||
|
||||
void analogWriteBuffered(pin_t pin, analog_t val) {
|
||||
if (pin == NO_PIN)
|
||||
return;
|
||||
else if (isNativePin(pin))
|
||||
::analogWrite(arduino_pin_cast(pin), val);
|
||||
else {
|
||||
auto el = getIOElementOfPin(pin);
|
||||
el->analogWriteBuffered(pin - el->getStart(), val);
|
||||
}
|
||||
}
|
||||
void analogWriteBuffered(pin_t pin, int val) {
|
||||
analogWriteBuffered(pin, (analog_t)val);
|
||||
}
|
||||
|
||||
void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val) {
|
||||
if (dataPin == NO_PIN || clockPin == NO_PIN)
|
||||
return;
|
||||
if (isNativePin(dataPin) && isNativePin(clockPin)) {
|
||||
::shiftOut(arduino_pin_cast(dataPin), arduino_pin_cast(clockPin),
|
||||
bitOrder, val);
|
||||
} else if (!isNativePin(dataPin) && !isNativePin(clockPin)) {
|
||||
auto dataEl = getIOElementOfPin(dataPin);
|
||||
auto dataPinN = dataPin - dataEl->getStart();
|
||||
auto clockEl = getIOElementOfPin(clockPin);
|
||||
auto clockPinN = clockPin - clockEl->getStart();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
|
||||
dataEl->digitalWrite(dataPinN, (val & mask) ? HIGH : LOW);
|
||||
clockEl->digitalWrite(clockPinN, HIGH);
|
||||
clockEl->digitalWrite(clockPinN, LOW);
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
uint8_t mask = bitOrder == LSBFIRST ? (1 << i) : (1 << (7 - i));
|
||||
digitalWrite(dataPin, (val & mask) ? HIGH : LOW);
|
||||
digitalWrite(clockPin, HIGH);
|
||||
digitalWrite(clockPin, LOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ExtIO
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Hardware/Arduino-Hardware-Types.hpp>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
class ExtendedIOElement;
|
||||
|
||||
namespace ExtIO {
|
||||
|
||||
inline bool isNativePin(pin_t pin) {
|
||||
return pin.pin < NUM_DIGITAL_PINS + NUM_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
ExtendedIOElement *getIOElementOfPinOrNull(pin_t pin);
|
||||
ExtendedIOElement *getIOElementOfPin(pin_t pin);
|
||||
|
||||
void pinMode(pin_t pin, PinMode_t mode);
|
||||
void digitalWrite(pin_t pin, PinStatus_t val);
|
||||
PinStatus_t digitalRead(pin_t pin);
|
||||
analog_t analogRead(pin_t pin);
|
||||
void analogWrite(pin_t pin, analog_t val);
|
||||
void analogWrite(pin_t pin, int val);
|
||||
void shiftOut(pin_t dataPin, pin_t clockPin, BitOrder_t bitOrder, uint8_t val);
|
||||
|
||||
void pinModeBuffered(pin_t pin, PinMode_t mode);
|
||||
void digitalWriteBuffered(pin_t pin, PinStatus_t val);
|
||||
PinStatus_t digitalReadBuffered(pin_t pin);
|
||||
analog_t analogReadBuffered(pin_t pin);
|
||||
void analogWriteBuffered(pin_t pin, analog_t val);
|
||||
void analogWriteBuffered(pin_t pin, int val);
|
||||
|
||||
} // namespace ExtIO
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Filters/EMA.hpp>
|
||||
#include <AH/Filters/Hysteresis.hpp>
|
||||
#include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp>
|
||||
#include <AH/Hardware/Hardware-Types.hpp>
|
||||
#include <AH/Math/IncreaseBitDepth.hpp>
|
||||
#include <AH/Math/MinMaxFix.hpp>
|
||||
#include <AH/STL/type_traits> // std::enable_if, std::is_constructible
|
||||
#include <AH/STL/utility> // std::forward
|
||||
#include <AH/Settings/SettingsWrapper.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief Helper to determine how many of the remaining bits of the filter
|
||||
* data types can be used to achieve higher precision.
|
||||
*/
|
||||
template <uint8_t FilterShiftFactor, class FilterType, class AnalogType>
|
||||
struct MaximumFilteredAnalogIncRes {
|
||||
constexpr static uint8_t value =
|
||||
min(sizeof(FilterType) * CHAR_BIT - ADC_BITS - FilterShiftFactor,
|
||||
sizeof(AnalogType) * CHAR_BIT - ADC_BITS);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief FilteredAnalog base class with generic MappingFunction.
|
||||
*
|
||||
* @see FilteredAnalog
|
||||
*/
|
||||
template <class MappingFunction, uint8_t Precision = 10,
|
||||
uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
|
||||
class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
|
||||
uint8_t IncRes = MaximumFilteredAnalogIncRes<
|
||||
FilterShiftFactor, FilterType, AnalogType>::value>
|
||||
class GenericFilteredAnalog {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new GenericFilteredAnalog object.
|
||||
*
|
||||
* @param analogPin
|
||||
* The analog pin to read from.
|
||||
* @param mapFn
|
||||
* The mapping function
|
||||
* @param initial
|
||||
* The initial value of the filter.
|
||||
*/
|
||||
GenericFilteredAnalog(pin_t analogPin, MappingFunction mapFn,
|
||||
AnalogType initial = 0)
|
||||
: analogPin(analogPin), mapFn(std::forward<MappingFunction>(mapFn)),
|
||||
filter(increaseBitDepth<ADC_BITS + IncRes, Precision, AnalogType,
|
||||
AnalogType>(initial)) {}
|
||||
|
||||
/// @copydoc GenericFilteredAnalog::GenericFilteredAnalog(pin_t,MappingFunction,AnalogType)
|
||||
GenericFilteredAnalog(ArduinoPin_t analogPin, MappingFunction mapFn,
|
||||
AnalogType initial = 0)
|
||||
: GenericFilteredAnalog(pin_t(analogPin),
|
||||
std::forward<MappingFunction>(mapFn), initial) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the filter to the given value.
|
||||
*
|
||||
* @param value
|
||||
* The value to reset the filter state to.
|
||||
*
|
||||
* @todo Should the filter be initialized to the first value that is read
|
||||
* instead of to zero? This would require adding a `begin` method.
|
||||
*/
|
||||
void reset(AnalogType value = 0) {
|
||||
AnalogType widevalue = increaseBitDepth<ADC_BITS + IncRes, Precision,
|
||||
AnalogType, AnalogType>(value);
|
||||
filter.reset(widevalue);
|
||||
hysteresis.setValue(widevalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the filtered value to the value that's currently being
|
||||
* measured at the analog input.
|
||||
*
|
||||
* This is useful to avoid transient effects upon initialization.
|
||||
*/
|
||||
void resetToCurrentValue() {
|
||||
AnalogType widevalue = getRawValue();
|
||||
filter.reset(widevalue);
|
||||
hysteresis.setValue(widevalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Specify a mapping function/functor that is applied to the analog
|
||||
* value after filtering and before applying hysteresis.
|
||||
*
|
||||
* @param fn
|
||||
* This functor should have a call operator that takes the filtered
|
||||
* value (of ADC_BITS + IncRes bits wide) as a parameter,
|
||||
* and returns a value of ADC_BITS + IncRes bits wide.
|
||||
*
|
||||
* @note Applying the mapping function before filtering could result in
|
||||
* the noise being amplified to such an extent that filtering it
|
||||
* afterwards would be ineffective.
|
||||
* Applying it after hysteresis would result in a lower resolution.
|
||||
* That's why the mapping function is applied after filtering and
|
||||
* before hysteresis.
|
||||
*/
|
||||
void map(MappingFunction fn) { mapFn = std::forward<MappingFunction>(fn); }
|
||||
|
||||
/**
|
||||
* @brief Get a reference to the mapping function.
|
||||
*/
|
||||
MappingFunction &getMappingFunction() { return mapFn; }
|
||||
/**
|
||||
* @brief Get a reference to the mapping function.
|
||||
*/
|
||||
const MappingFunction &getMappingFunction() const { return mapFn; }
|
||||
|
||||
/**
|
||||
* @brief Read the analog input value, apply the mapping function, and
|
||||
* update the average.
|
||||
*
|
||||
* @retval true
|
||||
* The value changed since last time it was updated.
|
||||
* @retval false
|
||||
* The value is still the same.
|
||||
*/
|
||||
bool update() {
|
||||
AnalogType input = getRawValue(); // read the raw analog input value
|
||||
input = filter.filter(input); // apply a low-pass EMA filter
|
||||
input = mapFnHelper(input); // apply the mapping function
|
||||
return hysteresis.update(input); // apply hysteresis, and return true
|
||||
// if the value changed since last time
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the filtered value of the analog input (with the mapping
|
||||
* function applied).
|
||||
*
|
||||
* @note This function just returns the value from the last call to
|
||||
* @ref update, it doesn't read the analog input again.
|
||||
*
|
||||
* @return The filtered value of the analog input, as a number
|
||||
* of `Precision` bits wide.
|
||||
*/
|
||||
AnalogType getValue() const { return hysteresis.getValue(); }
|
||||
|
||||
/**
|
||||
* @brief Get the filtered value of the analog input with the mapping
|
||||
* function applied as a floating point number from 0.0 to 1.0.
|
||||
*
|
||||
* @return The filtered value of the analog input, as a number
|
||||
* from 0.0 to 1.0.
|
||||
*/
|
||||
float getFloatValue() const {
|
||||
return getValue() * (1.0f / (ldexpf(1.0f, Precision) - 1.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the raw value of the analog input without any filtering or
|
||||
* mapping applied, but with its bit depth increased by @c IncRes.
|
||||
*/
|
||||
AnalogType getRawValue() const {
|
||||
AnalogType value = ExtIO::analogRead(analogPin);
|
||||
#ifdef ESP8266
|
||||
if (value > 1023)
|
||||
value = 1023;
|
||||
#endif
|
||||
return increaseBitDepth<ADC_BITS + IncRes, ADC_BITS, AnalogType>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the maximum value that can be returned from @ref getRawValue.
|
||||
*/
|
||||
constexpr static AnalogType getMaxRawValue() {
|
||||
return (1ul << (ADC_BITS + IncRes)) - 1ul;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Select the configured ADC resolution. By default, it is set to
|
||||
* the maximum resolution supported by the hardware.
|
||||
*
|
||||
* @see @ref ADC_BITS "ADC_BITS"
|
||||
* @see @ref ADCConfig.hpp "ADCConfig.hpp"
|
||||
*/
|
||||
static void setupADC() {
|
||||
#if HAS_ANALOG_READ_RESOLUTION
|
||||
analogReadResolution(ADC_BITS);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
/// Helper function that applies the mapping function if it's enabled.
|
||||
/// This function is only enabled if MappingFunction is explicitly
|
||||
/// convertible to bool.
|
||||
template <typename M = MappingFunction>
|
||||
typename std::enable_if<std::is_constructible<bool, M>::value,
|
||||
AnalogType>::type
|
||||
mapFnHelper(AnalogType input) {
|
||||
return bool(mapFn) ? mapFn(input) : input;
|
||||
}
|
||||
|
||||
/// Helper function that applies the mapping function without checking if
|
||||
/// it's enabled.
|
||||
/// This function is only enabled if MappingFunction is not convertible to
|
||||
/// bool.
|
||||
template <typename M = MappingFunction>
|
||||
typename std::enable_if<!std::is_constructible<bool, M>::value,
|
||||
AnalogType>::type
|
||||
mapFnHelper(AnalogType input) {
|
||||
return mapFn(input);
|
||||
}
|
||||
|
||||
private:
|
||||
pin_t analogPin;
|
||||
MappingFunction mapFn;
|
||||
|
||||
using EMA_t = EMA<FilterShiftFactor, AnalogType, FilterType>;
|
||||
|
||||
static_assert(
|
||||
ADC_BITS + IncRes + FilterShiftFactor <= sizeof(FilterType) * CHAR_BIT,
|
||||
"Error: FilterType is not wide enough to hold the maximum value");
|
||||
static_assert(
|
||||
ADC_BITS + IncRes <= sizeof(AnalogType) * CHAR_BIT,
|
||||
"Error: AnalogType is not wide enough to hold the maximum value");
|
||||
static_assert(
|
||||
Precision <= ADC_BITS + IncRes,
|
||||
"Error: Precision is larger than the increased ADC precision");
|
||||
static_assert(EMA_t::supports_range(AnalogType(0), getMaxRawValue()),
|
||||
"Error: EMA filter type doesn't support full ADC range");
|
||||
|
||||
EMA_t filter;
|
||||
Hysteresis<ADC_BITS + IncRes - Precision, AnalogType, AnalogType>
|
||||
hysteresis;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that reads and filters an analog input.
|
||||
*
|
||||
* A map function can be applied to the analog value (e.g. to compensate for
|
||||
* logarithmic taper potentiometers or to calibrate the range). The analog input
|
||||
* value is filtered using an exponential moving average filter. The default
|
||||
* settings for this filter can be changed in Settings.hpp.
|
||||
* After filtering, hysteresis is applied to prevent flipping back and forth
|
||||
* between two values when the input is not changing.
|
||||
*
|
||||
* @tparam Precision
|
||||
* The number of bits of precision the output should have.
|
||||
* @tparam FilterShiftFactor
|
||||
* The number of bits used for the EMA filter.
|
||||
* The pole location is
|
||||
* @f$ 1 - \left(\frac{1}{2}\right)^{\text{FilterShiftFactor}} @f$.
|
||||
* A lower shift factor means less filtering (@f$0@f$ is no filtering),
|
||||
* and a higher shift factor means more filtering (and more latency).
|
||||
* @tparam FilterType
|
||||
* The type to use for the intermediate types of the filter.
|
||||
* Should be at least
|
||||
* @f$ \text{ADC_BITS} + \text{IncRes} +
|
||||
* \text{FilterShiftFactor} @f$ bits wide.
|
||||
* @tparam AnalogType
|
||||
* The type to use for the analog values.
|
||||
* Should be at least @f$ \text{ADC_BITS} + \text{IncRes} @f$
|
||||
* bits wide.
|
||||
* @tparam IncRes
|
||||
* The number of bits to increase the resolution of the analog reading
|
||||
* by.
|
||||
*
|
||||
* @ingroup AH_HardwareUtils
|
||||
*/
|
||||
template <uint8_t Precision = 10,
|
||||
uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
|
||||
class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
|
||||
uint8_t IncRes = MaximumFilteredAnalogIncRes<
|
||||
FilterShiftFactor, FilterType, AnalogType>::value>
|
||||
class FilteredAnalog
|
||||
: public GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
|
||||
FilterShiftFactor, FilterType, AnalogType,
|
||||
IncRes> {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new FilteredAnalog object.
|
||||
*
|
||||
* @param analogPin
|
||||
* The analog pin to read from.
|
||||
* @param initial
|
||||
* The initial value of the filter.
|
||||
*/
|
||||
FilteredAnalog(pin_t analogPin, AnalogType initial = 0)
|
||||
: GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
|
||||
FilterShiftFactor, FilterType, AnalogType,
|
||||
IncRes>(analogPin, nullptr, initial) {}
|
||||
|
||||
/// @copydoc FilteredAnalog(pin_t,AnalogType)
|
||||
FilteredAnalog(ArduinoPin_t analogPin, AnalogType initial = 0)
|
||||
: FilteredAnalog(pin_t(analogPin), initial) {}
|
||||
|
||||
/**
|
||||
* @brief Construct a new FilteredAnalog object.
|
||||
*
|
||||
* **This constructor should not be used.**
|
||||
* It is just a way to easily create arrays of FilteredAnalog objects, and
|
||||
* initializing them later. Trying to update a default-constructed or
|
||||
* uninitialized FilteredAnalog object will result in a fatal runtime error.
|
||||
*/
|
||||
FilteredAnalog() : FilteredAnalog(NO_PIN) {}
|
||||
|
||||
/// A function pointer to a mapping function to map analog values.
|
||||
/// @see map()
|
||||
using MappingFunction = AnalogType (*)(AnalogType);
|
||||
|
||||
/**
|
||||
* @brief Invert the analog value. For example, if the precision is 10
|
||||
* bits, when the analog input measures 1023, the output will be 0,
|
||||
* and when the analog input measures 0, the output will be 1023.
|
||||
*
|
||||
* @note This overrides the mapping function set by the `map` method.
|
||||
*/
|
||||
void invert() {
|
||||
constexpr AnalogType maxval = FilteredAnalog::getMaxRawValue();
|
||||
this->map([](AnalogType val) -> AnalogType { return maxval - val; });
|
||||
}
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Containers/Array.hpp>
|
||||
#include <AH/PrintStream/PrintStream.hpp>
|
||||
#include <AH/STL/limits>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
using analog_t = uint16_t;
|
||||
using pin_int_t = uint_fast16_t;
|
||||
constexpr pin_int_t NO_PIN_INT =
|
||||
(std::numeric_limits<pin_int_t>::max() >> 1) + 1;
|
||||
|
||||
namespace ExtIO {
|
||||
struct pin_t {
|
||||
constexpr pin_t() = default;
|
||||
constexpr pin_t(pin_int_t pin) : pin(pin) {}
|
||||
|
||||
pin_int_t pin = NO_PIN_INT;
|
||||
|
||||
static_assert(std::is_unsigned<decltype(pin)>::value,
|
||||
"Error: pin_t should be an unsigned integer type");
|
||||
|
||||
pin_t &operator+=(pin_int_t b) { this->pin += b; return *this; }
|
||||
pin_t &operator++() { ++pin; return *this; }
|
||||
pin_t operator++(int) { pin_t t = *this; ++pin; return t; }
|
||||
pin_t &operator-=(pin_int_t b) { this->pin -= b; return *this; }
|
||||
pin_t &operator--() { --pin; return *this; }
|
||||
pin_t operator--(int) { pin_t t = *this; --pin; return t; }
|
||||
};
|
||||
constexpr inline bool operator==(pin_t a, pin_t b) { return a.pin == b.pin; }
|
||||
constexpr inline bool operator<(pin_t a, pin_t b) { return a.pin < b.pin; }
|
||||
constexpr inline bool operator<=(pin_t a, pin_t b) { return a.pin <= b.pin; }
|
||||
constexpr inline bool operator>(pin_t a, pin_t b) { return a.pin > b.pin; }
|
||||
constexpr inline bool operator>=(pin_t a, pin_t b) { return a.pin >= b.pin; }
|
||||
constexpr inline bool operator!=(pin_t a, pin_t b) { return !(a == b); }
|
||||
constexpr inline pin_int_t operator-(pin_t a, pin_t b) { return a.pin - b.pin; }
|
||||
constexpr inline pin_t operator-(pin_t a, pin_int_t b) { return a.pin - b; }
|
||||
constexpr inline pin_t operator+(pin_t a, pin_int_t b) { return a.pin + b; }
|
||||
constexpr inline pin_t operator+(pin_int_t a, pin_t b) { return a + b.pin; }
|
||||
constexpr inline pin_t operator*(pin_t a, pin_int_t b) { return a.pin * b; }
|
||||
constexpr inline pin_t operator*(pin_int_t a, pin_t b) { return a * b.pin; }
|
||||
inline Print &operator<<(Print &os, pin_t p) {
|
||||
using AH::operator<<;
|
||||
return os << +p.pin;
|
||||
}
|
||||
#ifndef ARDUINO
|
||||
inline std::ostream &operator<<(std::ostream &os, pin_t p) {
|
||||
return os << +p.pin;
|
||||
}
|
||||
#endif
|
||||
} // namespace ExtIO
|
||||
|
||||
using ExtIO::pin_t;
|
||||
|
||||
#ifdef NO_PIN
|
||||
#undef NO_PIN
|
||||
#endif
|
||||
|
||||
constexpr pin_t NO_PIN {};
|
||||
|
||||
template <size_t N>
|
||||
using PinList = Array<pin_t, N>;
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#include "IncrementButton.hpp"
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
IncrementButton::State IncrementButton::updateImplementation() {
|
||||
Button::State incrState = button.update();
|
||||
|
||||
if (incrState == Button::Released) {
|
||||
// Button released, don't do anything
|
||||
// This one is first to minimize overhead
|
||||
// because most of the time, the button will
|
||||
// be released
|
||||
return Nothing;
|
||||
} else if (incrState == Button::Rising) {
|
||||
auto res = longPressState == LongPress ? ReleasedLong : ReleasedShort;
|
||||
longPressState = Initial;
|
||||
return res;
|
||||
} else if (incrState == Button::Falling) {
|
||||
return IncrementShort;
|
||||
} else { // if (incrState == Button::Pressed)
|
||||
auto now = millis();
|
||||
if (longPressState == LongPress) {
|
||||
// still long pressed
|
||||
if (now - longPressRepeat >= LONG_PRESS_REPEAT_DELAY) {
|
||||
longPressRepeat += LONG_PRESS_REPEAT_DELAY;
|
||||
return IncrementHold;
|
||||
}
|
||||
} else if (button.stableTime(now) >= LONG_PRESS_DELAY) {
|
||||
// long press starts
|
||||
longPressState = LongPress;
|
||||
longPressRepeat = now;
|
||||
return IncrementLong;
|
||||
}
|
||||
}
|
||||
return Nothing;
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief A class for buttons that increment some counter or setting.
|
||||
*
|
||||
* It behaves the same way as a computer keyboard: when you press the button,
|
||||
* it increments the counter once. If you keep on pressing it for longer than
|
||||
* a certain threshold, it keeps on incrementing at a faster rate, until you
|
||||
* release it.
|
||||
*
|
||||
* @ingroup AH_HardwareUtils
|
||||
*/
|
||||
class IncrementButton {
|
||||
public:
|
||||
/**
|
||||
* @brief Create a IncrementButton.
|
||||
*
|
||||
* @param button
|
||||
* The button to read from.
|
||||
* The button is copied.
|
||||
*/
|
||||
IncrementButton(const Button &button) : button(button) {}
|
||||
|
||||
/// @see Button::begin
|
||||
void begin() { button.begin(); }
|
||||
|
||||
/**
|
||||
* @brief An enumeration of the different actions to be performed by the
|
||||
* counter.
|
||||
* @todo Add states for initial press.
|
||||
*/
|
||||
enum State {
|
||||
Nothing = 0, ///< The counter must not be incremented.
|
||||
IncrementShort, ///< The counter must be incremented (after short press).
|
||||
IncrementLong, ///< The counter must be incremented (after long press).
|
||||
IncrementHold, ///< The counter must be incremented (still pressed).
|
||||
ReleasedShort, ///< The button was released after a short press.
|
||||
ReleasedLong, ///< The button was released after a long press.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update and return the state of the increment button.
|
||||
*/
|
||||
State update() { return state = updateImplementation(); }
|
||||
|
||||
/**
|
||||
* @brief Return the state of the increment button without updating it.
|
||||
*
|
||||
* Returns the same value as the last @ref update call.
|
||||
*/
|
||||
State getState() const { return state; }
|
||||
|
||||
/// @see Button::invert
|
||||
void invert() { button.invert(); }
|
||||
|
||||
protected:
|
||||
State updateImplementation();
|
||||
|
||||
private:
|
||||
Button button;
|
||||
|
||||
enum {
|
||||
Initial,
|
||||
LongPress,
|
||||
} longPressState = Initial;
|
||||
unsigned long longPressRepeat;
|
||||
|
||||
State state = Nothing;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#include "IncrementDecrementButtons.hpp"
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
IncrementDecrementButtons::State
|
||||
IncrementDecrementButtons::updateImplementation() {
|
||||
Button::State incrState = incrementButton.update();
|
||||
Button::State decrState = decrementButton.update();
|
||||
|
||||
if (decrState == Button::Released && incrState == Button::Released) {
|
||||
// Both released
|
||||
} else if ((decrState == Button::Rising && incrState == Button::Released) ||
|
||||
(incrState == Button::Rising && decrState == Button::Released) ||
|
||||
(incrState == Button::Rising && decrState == Button::Rising)) {
|
||||
// One released, the other rising → nothing
|
||||
// now both released, so go to initial state
|
||||
longPressState = Initial;
|
||||
} else if (incrState == Button::Falling && decrState == Button::Falling) {
|
||||
// Both falling → reset
|
||||
// (rather unlikely, but just in case)
|
||||
longPressState = AfterReset;
|
||||
return Reset;
|
||||
} else if (incrState == Button::Falling) {
|
||||
if (decrState == Button::Pressed) {
|
||||
// One pressed, the other falling → reset
|
||||
longPressState = AfterReset;
|
||||
return Reset;
|
||||
} else {
|
||||
// Increment falling, the other released → increment
|
||||
return IncrementShort;
|
||||
}
|
||||
} else if (decrState == Button::Falling) {
|
||||
if (incrState == Button::Pressed) {
|
||||
// One pressed, the other falling → reset
|
||||
longPressState = AfterReset;
|
||||
return Reset;
|
||||
} else {
|
||||
// Decrement falling, the other released → decrement
|
||||
return DecrementShort;
|
||||
}
|
||||
} else if (incrState == Button::Pressed && decrState == Button::Pressed) {
|
||||
// Both pressed → nothing
|
||||
} else if (longPressState != AfterReset && incrState == Button::Pressed) {
|
||||
// Not reset and increment pressed → long press?
|
||||
auto now = millis();
|
||||
if (longPressState == LongPress) {
|
||||
if (now - longPressRepeat >= LONG_PRESS_REPEAT_DELAY) {
|
||||
longPressRepeat += LONG_PRESS_REPEAT_DELAY;
|
||||
return IncrementHold;
|
||||
}
|
||||
} else if (incrementButton.stableTime() >= LONG_PRESS_DELAY) {
|
||||
longPressState = LongPress;
|
||||
longPressRepeat = now;
|
||||
return IncrementLong;
|
||||
}
|
||||
} else if (longPressState != AfterReset && decrState == Button::Pressed) {
|
||||
// Not reset and decrement pressed → long press?
|
||||
auto now = millis();
|
||||
if (longPressState == LongPress) {
|
||||
if (now - longPressRepeat >= LONG_PRESS_REPEAT_DELAY) {
|
||||
longPressRepeat += LONG_PRESS_REPEAT_DELAY;
|
||||
return DecrementHold;
|
||||
}
|
||||
} else if (decrementButton.stableTime() >= LONG_PRESS_DELAY) {
|
||||
longPressState = LongPress;
|
||||
longPressRepeat = now;
|
||||
return DecrementLong;
|
||||
}
|
||||
}
|
||||
return Nothing;
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* ✔ */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/**
|
||||
* @brief A class for buttons that increment and decrement some counter or
|
||||
* setting.
|
||||
*
|
||||
* It behaves the same way as a computer keyboard: when you press the increment
|
||||
* (decrement) button, it increments (decrements) the counter once.
|
||||
* If you keep on pressing it for longer than a certain threshold, it keeps on
|
||||
* incrementing (decrementing) at a faster rate, until you release it.
|
||||
* If both the increment and the decrement button are pressed at once, it resets
|
||||
* the counter.
|
||||
*
|
||||
* @ingroup AH_HardwareUtils
|
||||
*/
|
||||
class IncrementDecrementButtons {
|
||||
public:
|
||||
/**
|
||||
* @brief Create a IncrementDecrementButtons object.
|
||||
*
|
||||
* @param incrementButton
|
||||
* The button to increment the counter.
|
||||
* The button is copied.
|
||||
* @param decrementButton
|
||||
* The button to decrement the counter.
|
||||
* The button is copied.
|
||||
*/
|
||||
IncrementDecrementButtons(const Button &incrementButton,
|
||||
const Button &decrementButton)
|
||||
: incrementButton(incrementButton), decrementButton(decrementButton) {}
|
||||
|
||||
/// @see Button::begin
|
||||
void begin() {
|
||||
incrementButton.begin();
|
||||
decrementButton.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief An enumeration of the different actions to be performed by the
|
||||
* counter.
|
||||
* @todo Add states for initial press.
|
||||
*/
|
||||
enum State {
|
||||
Nothing = 0, ///< The counter should not be incremented.
|
||||
IncrementShort, ///< The counter must be incremented (after short press).
|
||||
IncrementLong, ///< The counter must be incremented (after long press).
|
||||
IncrementHold, ///< The counter must be incremented (still pressed).
|
||||
DecrementShort, ///< The counter must be decremented (after short press).
|
||||
DecrementLong, ///< The counter must be decremented (after long press).
|
||||
DecrementHold, ///< The counter must be decremented (still pressed).
|
||||
Reset, ///< The counter should be reset to the initial value.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update and return the state of the increment/decrement button.
|
||||
*/
|
||||
State update() { return state = updateImplementation(); }
|
||||
|
||||
/**
|
||||
* @brief Return the state of the increment/decrement button without
|
||||
* updating it.
|
||||
*
|
||||
* Returns the same value as the last @ref update call.
|
||||
*/
|
||||
State getState() const { return state; }
|
||||
|
||||
/// @see Button::invert
|
||||
void invert() {
|
||||
incrementButton.invert();
|
||||
decrementButton.invert();
|
||||
}
|
||||
|
||||
protected:
|
||||
State updateImplementation();
|
||||
|
||||
private:
|
||||
Button incrementButton;
|
||||
Button decrementButton;
|
||||
|
||||
enum {
|
||||
Initial,
|
||||
LongPress,
|
||||
AfterReset,
|
||||
} longPressState = Initial;
|
||||
unsigned long longPressRepeat;
|
||||
State state = Nothing;
|
||||
};
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/STL/cstdint>
|
||||
#include <AH/STL/type_traits>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
#include <stddef.h>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// Divide by N using the default division operator, without explicit rounding
|
||||
/// This should be used for floating point types. For integers, prefer using
|
||||
/// @ref round_div_unsigned_int and @ref round_div_signed_int.
|
||||
template <uint8_t N, class T>
|
||||
struct round_div_default {
|
||||
static T div(T val) { return val / N; }
|
||||
};
|
||||
|
||||
/// Divide an unsigned integer by N, rounding the result.
|
||||
template <uint8_t N, class T>
|
||||
struct round_div_unsigned_int {
|
||||
static T div(T val) {
|
||||
return (val + (N / 2)) / N;
|
||||
static_assert(std::is_unsigned<T>::value && std::is_integral<T>::value,
|
||||
"This function is only valid for unsigned integers");
|
||||
}
|
||||
};
|
||||
|
||||
/// Divide a signed integer by N, rounding the result.
|
||||
template <uint8_t N, class T>
|
||||
struct round_div_signed_int {
|
||||
static T div(T val) {
|
||||
T offset = val >= 0 ? (N / 2) : (-N / 2);
|
||||
return (val + offset) / N;
|
||||
}
|
||||
};
|
||||
|
||||
/// Select the right rounding division operator, depending on whether T is a
|
||||
/// signed or unsigned integer.
|
||||
template <uint8_t N, class T>
|
||||
struct round_div_int
|
||||
: std::conditional<std::is_signed<T>::value, round_div_signed_int<N, T>,
|
||||
round_div_unsigned_int<N, T>>::type {};
|
||||
|
||||
/// Select the right rounding division operator, depending on whether T is an
|
||||
/// integer or not.
|
||||
template <uint8_t N, class T>
|
||||
struct round_div_helper
|
||||
: std::conditional<std::is_integral<T>::value, round_div_int<N, T>,
|
||||
round_div_default<N, T>>::type {};
|
||||
|
||||
/// Divide a number by N and round the result. Uses different specializations
|
||||
/// for integers to implement efficient rounding.
|
||||
template <size_t N, class T>
|
||||
T round_div(T val) {
|
||||
return round_div_helper<N, T>::div(val);
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/STL/type_traits> // enable_if
|
||||
#include <limits.h> // CHAR_BIT
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
|
||||
std::enable_if_t<(Bits_out <= 2 * Bits_in) && (Bits_out > Bits_in), T_out>
|
||||
increaseBitDepthImpl(T_in in) {
|
||||
constexpr size_t leftShift = Bits_out - Bits_in;
|
||||
constexpr size_t rightShift = Bits_in - leftShift;
|
||||
return (static_cast<T_out>(in) << leftShift) | (in >> rightShift);
|
||||
}
|
||||
|
||||
template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
|
||||
std::enable_if_t<(Bits_out <= Bits_in), T_out> increaseBitDepthImpl(T_in in) {
|
||||
constexpr size_t rightShift = Bits_in - Bits_out;
|
||||
return static_cast<T_out>(in >> rightShift);
|
||||
}
|
||||
|
||||
template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
|
||||
std::enable_if_t<(Bits_out > 2 * Bits_in), T_out>
|
||||
increaseBitDepthImpl(T_in in) {
|
||||
constexpr size_t leftShift = Bits_out - Bits_in;
|
||||
return (static_cast<T_out>(in) << leftShift) |
|
||||
increaseBitDepthImpl<leftShift, Bits_in, T_out>(in);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// @addtogroup AH_Math
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief Increase the bit depth of the given value from `Bits_in` bits wide
|
||||
* to `Bits_out` bits wide, (approximately) evenly distributing the
|
||||
* error across the entire range, such that the error for each element
|
||||
* is between -1 and +1.
|
||||
*
|
||||
* @see @ref increaseBitDepthMiddle
|
||||
*
|
||||
* For example, converting 3-bit numbers to 7-bit numbers would result in the
|
||||
* following:
|
||||
*
|
||||
* | in (dec) | in (bin) | out (bin) | out (dec) | exact | error |
|
||||
* |:--------:|:--------:|:---------:|:---------:|:------:|:-----:|
|
||||
* | 0 | 000 | 000'0000 | 0 | 0.00 | +0.00 |
|
||||
* | 1 | 001 | 001'0010 | 18 | 18.14 | +0.14 |
|
||||
* | 2 | 010 | 010'0100 | 36 | 36.29 | +0.29 |
|
||||
* | 3 | 011 | 011'0110 | 54 | 54.43 | +0.43 |
|
||||
* | 4 | 100 | 100'1001 | 73 | 72.57 | -0.43 |
|
||||
* | 5 | 101 | 101'1011 | 91 | 90.71 | -0.29 |
|
||||
* | 6 | 110 | 110'1101 | 109 | 108.86 | -0.14 |
|
||||
* | 7 | 111 | 111'1111 | 127 | 127.00 | +0.00 |
|
||||
*
|
||||
* The following is a comparison to the @ref increaseBitDepthMiddle function.
|
||||
*
|
||||
* @image html increase-bit-depth.svg
|
||||
*
|
||||
* @tparam Bits_out
|
||||
* The number of bits of the output range.
|
||||
* @tparam Bits_in
|
||||
* The number of bits of the input range.
|
||||
* @tparam T_out
|
||||
* The type of the output (return type).
|
||||
* @tparam T_in
|
||||
* The type of the input.
|
||||
* @param in
|
||||
* The value to scale up.
|
||||
* @return The scaled up value.
|
||||
*/
|
||||
template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
|
||||
T_out increaseBitDepth(T_in in) {
|
||||
static_assert(Bits_in <= sizeof(T_in) * CHAR_BIT,
|
||||
"Error: Bits_in > bits(T_in)");
|
||||
static_assert(Bits_out <= sizeof(T_out) * CHAR_BIT,
|
||||
"Error: Bits_out > bits(T_out)");
|
||||
return detail::increaseBitDepthImpl<Bits_out, Bits_in, T_out>(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increase the bit depth of the given value from `Bits_in` bits wide
|
||||
* to `Bits_out` bits wide, while ensuring that the middle of the input
|
||||
* range maps exactly to the middle of the output range, i.e.
|
||||
* @f$ 2^{\texttt{Bits\_in} - 1} @f$ maps to
|
||||
* @f$ 2^{\texttt{Bits\_out} - 1} @f$.
|
||||
*
|
||||
* @see @ref increaseBitDepth
|
||||
*
|
||||
* For example, converting 3-bit numbers to 7-bit numbers would result in the
|
||||
* following:
|
||||
*
|
||||
* | in (dec) | in (bin) | out (bin) | out (dec) | exact | error |
|
||||
* |:--------:|:--------:|:---------:|:---------:|:------:|:-----:|
|
||||
* | 0 | 000 | 000'0000 | 0 | 0.00 | +0.00 |
|
||||
* | 1 | 001 | 001'0000 | 16 | 18.14 | -2.14 |
|
||||
* | 2 | 010 | 010'0000 | 32 | 36.29 | -4.29 |
|
||||
* | 3 | 011 | 011'0000 | 48 | 54.43 | -6.43 |
|
||||
* | 4 | 100 | 100'0000 | 64 | 72.57 | -8.57 |
|
||||
* | 5 | 101 | 101'0101 | 85 | 90.71 | -5.71 |
|
||||
* | 6 | 110 | 110'1010 | 106 | 108.86 | -2.86 |
|
||||
* | 7 | 111 | 111'1111 | 127 | 127.00 | +0.00 |
|
||||
*
|
||||
* The following is a comparison to the @ref increaseBitDepth function.
|
||||
*
|
||||
* @image html increase-bit-depth.svg
|
||||
*
|
||||
* @tparam Bits_out
|
||||
* The number of bits of the output range.
|
||||
* @tparam Bits_in
|
||||
* The number of bits of the input range.
|
||||
* @tparam T_out
|
||||
* The type of the output (return type).
|
||||
* @tparam T_in
|
||||
* The type of the input.
|
||||
* @param in
|
||||
* The value to scale up.
|
||||
* @return The scaled up value.
|
||||
*/
|
||||
template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
|
||||
T_out increaseBitDepthMiddle(T_in in) {
|
||||
static_assert(Bits_in <= sizeof(T_in) * CHAR_BIT,
|
||||
"Error: Bits_in > bits(T_in)");
|
||||
static_assert(Bits_out <= sizeof(T_out) * CHAR_BIT,
|
||||
"Error: Bits_out > bits(T_out)");
|
||||
constexpr size_t leftShift = Bits_out - Bits_in;
|
||||
T_in half = T_in {1} << (Bits_in - 1);
|
||||
T_out out = static_cast<T_out>(in) << leftShift;
|
||||
if (in > half) {
|
||||
T_in repeat = in & (half - 1);
|
||||
out |= increaseBitDepth<leftShift, Bits_in - 1, T_out>(repeat);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// Return the smaller of two numbers/objects.
|
||||
/// @ingroup AH_Math
|
||||
template <class T, class U>
|
||||
constexpr auto min(const T &a, const U &b) -> decltype(b < a ? b : a) {
|
||||
return b < a ? b : a;
|
||||
}
|
||||
|
||||
/// Return the larger of two numbers/objects.
|
||||
/// @ingroup AH_Math
|
||||
template <class T, class U>
|
||||
constexpr auto max(const T &a, const U &b) -> decltype(a < b ? b : a) {
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
// https://github.com/tttapa/Arduino-PrintStream/blob/6a9e0d365be0b3d84187daa2a8a7bda8d541472e/src/PrintStream.cpp
|
||||
|
||||
#include "PrintStream.hpp"
|
||||
|
||||
// LCOV_EXCL_START
|
||||
|
||||
#if not defined(ARDUINO_ARCH_ESP32) && not defined(ARDUINO_ARCH_SAM) && \
|
||||
not defined(ARDUINO_API_VERSION) && not defined(ArduinoFake) && \
|
||||
not defined(ARDUINO_ARCH_STM32)
|
||||
#define FLUSH
|
||||
#endif
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/* #define OCT 8 */
|
||||
|
||||
uint8_t formatPrintStream = DEC;
|
||||
bool boolalphaPrintStream = false;
|
||||
bool leadingZerosPrintStream = false;
|
||||
uint8_t precisionPrintStream = 2;
|
||||
char byteSeparatorPrintStream = '\0';
|
||||
enum : char { LOWERCASE = 0x7F, UPPERCASE = 0x5F } casePrintStream = LOWERCASE;
|
||||
bool showbasePrintStream = false;
|
||||
|
||||
template <class T>
|
||||
Print &printIntegral(Print &printer, T i);
|
||||
|
||||
Print &endl(Print &printer) {
|
||||
printer.println();
|
||||
#ifdef FLUSH
|
||||
printer.flush();
|
||||
#endif
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &uppercase(Print &printer) {
|
||||
casePrintStream = UPPERCASE;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &nouppercase(Print &printer) {
|
||||
casePrintStream = LOWERCASE;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &showbase(Print &printer) {
|
||||
showbasePrintStream = true;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &noshowbase(Print &printer) {
|
||||
showbasePrintStream = false;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &flush(Print &printer) {
|
||||
#ifdef FLUSH
|
||||
printer.flush();
|
||||
#endif
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &hex(Print &printer) {
|
||||
formatPrintStream = HEX;
|
||||
return printer;
|
||||
}
|
||||
|
||||
/* Print &oct(Print &printer) {
|
||||
formatPrintStream = OCT;
|
||||
return printer;
|
||||
} */
|
||||
|
||||
Print &bin(Print &printer) {
|
||||
formatPrintStream = BIN;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &dec(Print &printer) {
|
||||
formatPrintStream = DEC;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &boolalpha(Print &printer) {
|
||||
boolalphaPrintStream = true;
|
||||
return printer;
|
||||
}
|
||||
Print &noboolalpha(Print &printer) {
|
||||
boolalphaPrintStream = false;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &leadingzeros(Print &printer) {
|
||||
leadingZerosPrintStream = true;
|
||||
return printer;
|
||||
}
|
||||
Print &noleadingzeros(Print &printer) {
|
||||
leadingZerosPrintStream = false;
|
||||
return printer;
|
||||
}
|
||||
Print &operator<<(Print &printer, const __FlashStringHelper *s) {
|
||||
printer.print(s);
|
||||
return printer;
|
||||
}
|
||||
#ifdef ARDUINO
|
||||
Print &operator<<(Print &printer, const String &s) {
|
||||
printer.print(s);
|
||||
return printer;
|
||||
}
|
||||
#endif
|
||||
Print &operator<<(Print &printer, const char s[]) {
|
||||
printer.print(s);
|
||||
return printer;
|
||||
}
|
||||
Print &operator<<(Print &printer, char c) {
|
||||
printer.print(c);
|
||||
return printer;
|
||||
}
|
||||
Print &operator<<(Print &printer, unsigned char i) {
|
||||
return printIntegral(printer, i);
|
||||
}
|
||||
Print &operator<<(Print &printer, int i) { return printIntegral(printer, i); }
|
||||
Print &operator<<(Print &printer, unsigned int i) {
|
||||
return printIntegral(printer, i);
|
||||
}
|
||||
Print &operator<<(Print &printer, int8_t i) {
|
||||
return printIntegral(printer, i);
|
||||
}
|
||||
Print &operator<<(Print &printer, long i) { return printIntegral(printer, i); }
|
||||
Print &operator<<(Print &printer, unsigned long i) {
|
||||
return printIntegral(printer, i);
|
||||
}
|
||||
Print &operator<<(Print &printer, double d) {
|
||||
printer.print(d, +precisionPrintStream);
|
||||
return printer;
|
||||
}
|
||||
Print &operator<<(Print &printer, float f) {
|
||||
return printer << static_cast<double>(f);
|
||||
}
|
||||
Print &operator<<(Print &printer, const Printable &p) {
|
||||
printer.print(p);
|
||||
return printer;
|
||||
}
|
||||
Print &operator<<(Print &printer, bool b) {
|
||||
if (boolalphaPrintStream)
|
||||
printer.print(b ? F("true") : F("false"));
|
||||
else
|
||||
printer.print(b);
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &operator<<(Print &printer, manipulator pf) { return pf(printer); }
|
||||
|
||||
Setbase setbase(uint8_t base) { return {base}; }
|
||||
Print &operator<<(Print &printer, Setbase f) {
|
||||
formatPrintStream = f.M_base;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Setbytesep setbytesep(char bytesep) { return {bytesep}; }
|
||||
Print &operator<<(Print &printer, Setbytesep f) {
|
||||
byteSeparatorPrintStream = f.M_bytesep;
|
||||
return printer;
|
||||
}
|
||||
|
||||
Setprecision setprecision(int n) { return {n}; }
|
||||
Print &operator<<(Print &printer, Setprecision f) {
|
||||
precisionPrintStream = f.M_n;
|
||||
return printer;
|
||||
}
|
||||
|
||||
static char nibble_to_hex(
|
||||
uint8_t nibble) { // convert a 4-bit nibble to a hexadecimal character
|
||||
nibble &= 0xF;
|
||||
return nibble > 9 ? nibble - 10 + ('a' & casePrintStream) : nibble + '0';
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER != __LITTLE_ENDIAN
|
||||
#error "Byte order not supported"
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void printHex(Print &printer, T val) {
|
||||
if (showbasePrintStream)
|
||||
printer.print("0x");
|
||||
bool nonZero = false;
|
||||
for (int i = sizeof(val) - 1; i >= 0; i--) {
|
||||
uint8_t currByte = ((uint8_t *)&val)[i];
|
||||
if (currByte != 0 || i == 0)
|
||||
nonZero = true;
|
||||
if (leadingZerosPrintStream || nonZero) {
|
||||
printer.print(nibble_to_hex(currByte >> 4));
|
||||
printer.print(nibble_to_hex(currByte));
|
||||
if (byteSeparatorPrintStream && i)
|
||||
printer.print(byteSeparatorPrintStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void printBin(Print &printer, T val) {
|
||||
if (showbasePrintStream)
|
||||
printer.print("0b");
|
||||
bool nonZero = false;
|
||||
for (int i = sizeof(val) - 1; i >= 0; i--) {
|
||||
uint8_t currByte = ((uint8_t *)&val)[i];
|
||||
for (int j = 7; j >= 0; j--) {
|
||||
uint8_t currBit = currByte & 0x80;
|
||||
if (currBit != 0 || (i == 0 && j == 0))
|
||||
nonZero = true;
|
||||
if (leadingZerosPrintStream || nonZero)
|
||||
printer.print(currBit ? '1' : '0');
|
||||
currByte <<= 1;
|
||||
}
|
||||
if (byteSeparatorPrintStream && i &&
|
||||
(leadingZerosPrintStream || nonZero))
|
||||
printer.print(byteSeparatorPrintStream);
|
||||
}
|
||||
}
|
||||
|
||||
/* template <class T>
|
||||
void printOct(Print &printer, T val)
|
||||
{
|
||||
; // TODO
|
||||
} */
|
||||
|
||||
template <class T>
|
||||
Print &printIntegral(Print &printer, T i) {
|
||||
switch (formatPrintStream) {
|
||||
case DEC: printer.print(i); break;
|
||||
case HEX: printHex(printer, i); break;
|
||||
case BIN: printBin(printer, i); break;
|
||||
/* case OCT:
|
||||
printOct(printer, i);
|
||||
break; */
|
||||
default: break;
|
||||
}
|
||||
return printer;
|
||||
}
|
||||
|
||||
Print &operator<<(Print &p, HexDump h) {
|
||||
if (h.length == 0)
|
||||
return p;
|
||||
|
||||
auto temp_case = casePrintStream;
|
||||
casePrintStream = UPPERCASE;
|
||||
while (h.length-- > 1) {
|
||||
printHex(p, *h.data++);
|
||||
p.print(' ');
|
||||
}
|
||||
printHex(p, *h.data++);
|
||||
casePrintStream = temp_case;
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
std::ostream &operator<<(std::ostream &p, HexDump h) {
|
||||
if (h.length == 0)
|
||||
return p;
|
||||
|
||||
auto hex_nibble_to_char = [](uint8_t nibble) -> char {
|
||||
nibble &= 0xF;
|
||||
return nibble > 9 ? nibble - 10 + 'A' : nibble + '0';
|
||||
};
|
||||
auto printHex = [&](std::ostream &p, uint8_t b) {
|
||||
p << hex_nibble_to_char(b >> 4) << hex_nibble_to_char(b);
|
||||
};
|
||||
|
||||
while (h.length-- > 1) {
|
||||
printHex(p, *h.data++);
|
||||
p << ' ';
|
||||
}
|
||||
printHex(p, *h.data++);
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
// LCOV_EXCL_STOP
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* @brief [PrintStream library](https://github.com/tttapa/Arduino-PrintStream/blob/6a9e0d365be0b3d84187daa2a8a7bda8d541472e/src/PrintStream.h)
|
||||
*/
|
||||
|
||||
#ifndef PrintStream_h
|
||||
#define PrintStream_h
|
||||
|
||||
#include <platform/pico_shim.h>
|
||||
#include <AH/Settings/NamespaceSettings.hpp>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
/// @addtogroup AH_PrintStream
|
||||
/// @{
|
||||
|
||||
typedef Print &manipulator(Print &);
|
||||
|
||||
Print &endl(Print &printer);
|
||||
Print &flush(Print &printer);
|
||||
Print &hex(Print &printer);
|
||||
Print &bin(Print &printer);
|
||||
Print &dec(Print &printer);
|
||||
/* Print &oct(Print &printer); */
|
||||
Print &boolalpha(Print &printer);
|
||||
Print &noboolalpha(Print &printer);
|
||||
Print &leadingzeros(Print &printer);
|
||||
Print &noleadingzeros(Print &printer);
|
||||
Print &uppercase(Print &printer);
|
||||
Print &nouppercase(Print &printer);
|
||||
Print &showbase(Print &printer);
|
||||
Print &noshowbase(Print &printer);
|
||||
|
||||
Print &operator<<(Print &printer, const __FlashStringHelper *s);
|
||||
#ifdef ARDUINO
|
||||
Print &operator<<(Print &printer, const String &s);
|
||||
#endif
|
||||
Print &operator<<(Print &printer, const char s[]);
|
||||
Print &operator<<(Print &printer, char c);
|
||||
Print &operator<<(Print &printer, unsigned char c);
|
||||
Print &operator<<(Print &printer, int i);
|
||||
Print &operator<<(Print &printer, unsigned int i);
|
||||
Print &operator<<(Print &printer, int8_t i);
|
||||
Print &operator<<(Print &printer, long i);
|
||||
Print &operator<<(Print &printer, unsigned long i);
|
||||
Print &operator<<(Print &printer, float f);
|
||||
Print &operator<<(Print &printer, double d);
|
||||
Print &operator<<(Print &printer, const Printable &p);
|
||||
Print &operator<<(Print &printer, bool b);
|
||||
|
||||
Print &operator<<(Print &printer, manipulator pf);
|
||||
|
||||
struct Setbase {
|
||||
uint8_t M_base;
|
||||
};
|
||||
Setbase setbase(uint8_t base);
|
||||
Print &operator<<(Print &printer, Setbase f);
|
||||
|
||||
struct Setprecision {
|
||||
int M_n;
|
||||
};
|
||||
Setprecision setprecision(int n);
|
||||
Print &operator<<(Print &printer, Setprecision f);
|
||||
|
||||
struct Setbytesep {
|
||||
char M_bytesep;
|
||||
};
|
||||
Setbytesep setbytesep(char bytesep);
|
||||
Print &operator<<(Print &printer, Setbytesep f);
|
||||
|
||||
struct HexDump {
|
||||
HexDump(const uint8_t *data, size_t length) : data(data), length(length) {}
|
||||
template <size_t N>
|
||||
explicit HexDump(const uint8_t (&data)[N]) : HexDump {data, N} {}
|
||||
const uint8_t *data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
Print &operator<<(Print &p, HexDump h);
|
||||
|
||||
/// @}
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
BEGIN_AH_NAMESPACE
|
||||
|
||||
// TODO: check conflicts between Arduino version and C++ STL version
|
||||
using std::endl;
|
||||
// using std::setbase;
|
||||
// using std::setprecision;
|
||||
using std::boolalpha;
|
||||
using std::dec;
|
||||
using std::flush;
|
||||
using std::hex;
|
||||
using std::noboolalpha;
|
||||
using std::noshowbase;
|
||||
using std::nouppercase;
|
||||
using std::showbase;
|
||||
using std::uppercase;
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, uint8_t u) {
|
||||
// I'm lazy, I should probably implement one for uint8_t to get the leading
|
||||
// zeros right
|
||||
return os << static_cast<unsigned short>(u);
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const __FlashStringHelper *s) {
|
||||
return os << reinterpret_cast<const char *>(s);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &p, HexDump h);
|
||||
|
||||
END_AH_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
||||
#include <Settings/NamespaceSettings.hpp>
|
||||
|
||||
BEGIN_CS_NAMESPACE
|
||||
using AH::operator<<;
|
||||
using AH::manipulator;
|
||||
using AH::endl;
|
||||
using AH::flush;
|
||||
using AH::hex;
|
||||
using AH::bin;
|
||||
using AH::dec;
|
||||
using AH::boolalpha;
|
||||
using AH::noboolalpha;
|
||||
using AH::leadingzeros;
|
||||
using AH::noleadingzeros;
|
||||
using AH::uppercase;
|
||||
using AH::nouppercase;
|
||||
using AH::showbase;
|
||||
using AH::noshowbase;
|
||||
using AH::setbase;
|
||||
using AH::setprecision;
|
||||
using AH::setbytesep;
|
||||
END_CS_NAMESPACE
|
||||
|
||||
#endif // PrintStream_h
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// <algorithm> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file include/algorithm
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALGORITHM
|
||||
#define _GLIBCXX_ALGORITHM 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "utility" // UK-300.
|
||||
#include "bits/stl_algobase.h"
|
||||
#include "bits/stl_algo.h"
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/algorithm>
|
||||
#endif
|
||||
|
||||
#endif /* _GLIBCXX_ALGORITHM */
|
||||
|
|
@ -0,0 +1,399 @@
|
|||
// <array> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/array
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ARRAY
|
||||
#define _GLIBCXX_ARRAY 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include "bits/c++0x_warning.h"
|
||||
#else
|
||||
|
||||
#include "utility"
|
||||
#include "bits/stl_algobase.h"
|
||||
#include "bits/range_access.h"
|
||||
|
||||
#ifndef __AVR__
|
||||
#include <stdexcept>
|
||||
#else
|
||||
#include <AH/Error/Error.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
struct __array_traits
|
||||
{
|
||||
typedef _Tp _Type[_Nm];
|
||||
typedef __is_swappable<_Tp> _Is_swappable;
|
||||
typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable;
|
||||
|
||||
static constexpr _Tp&
|
||||
_S_ref(const _Type& __t, std::size_t __n) noexcept
|
||||
{ return const_cast<_Tp&>(__t[__n]); }
|
||||
|
||||
static constexpr _Tp*
|
||||
_S_ptr(const _Type& __t) noexcept
|
||||
{ return const_cast<_Tp*>(__t); }
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __array_traits<_Tp, 0>
|
||||
{
|
||||
struct _Type { };
|
||||
typedef true_type _Is_swappable;
|
||||
typedef true_type _Is_nothrow_swappable;
|
||||
|
||||
static constexpr _Tp&
|
||||
_S_ref(const _Type&, std::size_t) noexcept
|
||||
{ return *static_cast<_Tp*>(nullptr); }
|
||||
|
||||
static constexpr _Tp*
|
||||
_S_ptr(const _Type&) noexcept
|
||||
{ return nullptr; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A standard container for storing a fixed size sequence of elements.
|
||||
*
|
||||
* @ingroup sequences
|
||||
*
|
||||
* Meets the requirements of a <a href="tables.html#65">container</a>, a
|
||||
* <a href="tables.html#66">reversible container</a>, and a
|
||||
* <a href="tables.html#67">sequence</a>.
|
||||
*
|
||||
* Sets support random access iterators.
|
||||
*
|
||||
* @tparam Tp Type of element. Required to be a complete type.
|
||||
* @tparam N Number of elements.
|
||||
*/
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
struct array
|
||||
{
|
||||
typedef _Tp value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
// Support for zero-sized arrays mandatory.
|
||||
typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type;
|
||||
typename _AT_Type::_Type _M_elems;
|
||||
|
||||
// No explicit construct/copy/destroy for aggregate type.
|
||||
|
||||
// DR 776.
|
||||
void
|
||||
fill(const value_type& __u)
|
||||
{ std::fill_n(begin(), size(), __u); }
|
||||
|
||||
void
|
||||
swap(array& __other)
|
||||
noexcept(_AT_Type::_Is_nothrow_swappable::value)
|
||||
{ std::swap_ranges(begin(), end(), __other.begin()); }
|
||||
|
||||
// Iterators.
|
||||
_GLIBCXX17_CONSTEXPR iterator
|
||||
begin() noexcept
|
||||
{ return iterator(data()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
begin() const noexcept
|
||||
{ return const_iterator(data()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR iterator
|
||||
end() noexcept
|
||||
{ return iterator(data() + _Nm); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
end() const noexcept
|
||||
{ return const_iterator(data() + _Nm); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||
rbegin() noexcept
|
||||
{ return reverse_iterator(end()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
rbegin() const noexcept
|
||||
{ return const_reverse_iterator(end()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||
rend() noexcept
|
||||
{ return reverse_iterator(begin()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
rend() const noexcept
|
||||
{ return const_reverse_iterator(begin()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
cbegin() const noexcept
|
||||
{ return const_iterator(data()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_iterator
|
||||
cend() const noexcept
|
||||
{ return const_iterator(data() + _Nm); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
crbegin() const noexcept
|
||||
{ return const_reverse_iterator(end()); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||
crend() const noexcept
|
||||
{ return const_reverse_iterator(begin()); }
|
||||
|
||||
// Capacity.
|
||||
constexpr size_type
|
||||
size() const noexcept { return _Nm; }
|
||||
|
||||
constexpr size_type
|
||||
max_size() const noexcept { return _Nm; }
|
||||
|
||||
constexpr bool
|
||||
empty() const noexcept { return size() == 0; }
|
||||
|
||||
// Element access.
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
operator[](size_type __n) noexcept
|
||||
{ return _AT_Type::_S_ref(_M_elems, __n); }
|
||||
|
||||
constexpr const_reference
|
||||
operator[](size_type __n) const noexcept
|
||||
{ return _AT_Type::_S_ref(_M_elems, __n); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
at(size_type __n)
|
||||
{
|
||||
#ifndef __AVR__
|
||||
if (__n >= _Nm)
|
||||
std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||
">= _Nm (which is %zu)"),
|
||||
__n, _Nm);
|
||||
#else
|
||||
if (__n >= _Nm) {
|
||||
ERROR(F("array::at: __n (which is ") << __n << ") " <<
|
||||
F(">= _Nm (which is ") << _Nm << ")", 0x6784);
|
||||
__n = _Nm - 1;
|
||||
}
|
||||
#endif
|
||||
return _AT_Type::_S_ref(_M_elems, __n);
|
||||
}
|
||||
|
||||
constexpr const_reference
|
||||
at(size_type __n) const
|
||||
{
|
||||
// Result of conditional expression must be an lvalue so use
|
||||
// boolean ? lvalue : (throw-expr, lvalue)
|
||||
#ifndef __AVR__
|
||||
return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
|
||||
: (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||
">= _Nm (which is %zu)"),
|
||||
__n, _Nm),
|
||||
_AT_Type::_S_ref(_M_elems, 0));
|
||||
#else
|
||||
return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
|
||||
: ([=] {ERROR(F("array::at: __n (which is ") << __n << ") " <<
|
||||
F(">= _Nm (which is ") << _Nm << ")", 0x6784);}(),
|
||||
_AT_Type::_S_ref(_M_elems, _Nm - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
front() noexcept
|
||||
{ return *begin(); }
|
||||
|
||||
constexpr const_reference
|
||||
front() const noexcept
|
||||
{ return _AT_Type::_S_ref(_M_elems, 0); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR reference
|
||||
back() noexcept
|
||||
{ return _Nm ? *(end() - 1) : *end(); }
|
||||
|
||||
constexpr const_reference
|
||||
back() const noexcept
|
||||
{
|
||||
return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
|
||||
: _AT_Type::_S_ref(_M_elems, 0);
|
||||
}
|
||||
|
||||
_GLIBCXX17_CONSTEXPR pointer
|
||||
data() noexcept
|
||||
{ return _AT_Type::_S_ptr(_M_elems); }
|
||||
|
||||
_GLIBCXX17_CONSTEXPR const_pointer
|
||||
data() const noexcept
|
||||
{ return _AT_Type::_S_ptr(_M_elems); }
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
template<typename _Tp, typename... _Up>
|
||||
array(_Tp, _Up...)
|
||||
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
|
||||
1 + sizeof...(_Up)>;
|
||||
#endif
|
||||
|
||||
// Array comparisons.
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return std::equal(__one.begin(), __one.end(), __two.begin()); }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one == __two); }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||
{
|
||||
return std::lexicographical_compare(__a.begin(), __a.end(),
|
||||
__b.begin(), __b.end());
|
||||
}
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return __two < __one; }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one > __two); }
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline bool
|
||||
operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||
{ return !(__one < __two); }
|
||||
|
||||
// Specialized algorithms.
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
inline
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
// Constrained free swap overload, see p0185r1
|
||||
typename enable_if<
|
||||
_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value
|
||||
>::type
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
|
||||
noexcept(noexcept(__one.swap(__two)))
|
||||
{ __one.swap(__two); }
|
||||
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
typename enable_if<
|
||||
!_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
|
||||
swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
|
||||
#endif
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
constexpr _Tp&
|
||||
get(array<_Tp, _Nm>& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
|
||||
_S_ref(__arr._M_elems, _Int);
|
||||
}
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
constexpr _Tp&&
|
||||
get(array<_Tp, _Nm>&& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
|
||||
}
|
||||
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
constexpr const _Tp&
|
||||
get(const array<_Tp, _Nm>& __arr) noexcept
|
||||
{
|
||||
static_assert(_Int < _Nm, "array index is within bounds");
|
||||
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
|
||||
_S_ref(__arr._M_elems, _Int);
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_CONTAINER
|
||||
} // namespace std
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Tuple interface to class template array.
|
||||
|
||||
/// tuple_size
|
||||
template<typename _Tp>
|
||||
class tuple_size;
|
||||
|
||||
/// Partial specialization for std::array
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>>
|
||||
: public integral_constant<std::size_t, _Nm> { };
|
||||
|
||||
/// tuple_element
|
||||
template<std::size_t _Int, typename _Tp>
|
||||
class tuple_element;
|
||||
|
||||
/// Partial specialization for std::array
|
||||
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||
struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>>
|
||||
{
|
||||
static_assert(_Int < _Nm, "index is out of bounds");
|
||||
typedef _Tp type;
|
||||
};
|
||||
|
||||
template<typename _Tp, std::size_t _Nm>
|
||||
struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type
|
||||
{ };
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#ifdef _GLIBCXX_DEBUG
|
||||
# include <debug/array>
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_PROFILE
|
||||
# include <profile/array>
|
||||
#endif
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _GLIBCXX_ARRAY
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
// Functor implementations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996-1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file backward/binders.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{functional}
|
||||
*/
|
||||
|
||||
#ifndef _BACKWARD_BINDERS_H
|
||||
#define _BACKWARD_BINDERS_H 1
|
||||
|
||||
// Suppress deprecated warning for this file.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// 20.3.6 binders
|
||||
/** @defgroup binders Binder Classes
|
||||
* @ingroup functors
|
||||
*
|
||||
* Binders turn functions/functors with two arguments into functors
|
||||
* with a single argument, storing an argument to be applied later.
|
||||
* For example, a variable @c B of type @c binder1st is constructed
|
||||
* from a functor @c f and an argument @c x. Later, B's @c
|
||||
* operator() is called with a single argument @c y. The return
|
||||
* value is the value of @c f(x,y). @c B can be @a called with
|
||||
* various arguments (y1, y2, ...) and will in turn call @c
|
||||
* f(x,y1), @c f(x,y2), ...
|
||||
*
|
||||
* The function @c bind1st is provided to save some typing. It takes the
|
||||
* function and an argument as parameters, and returns an instance of
|
||||
* @c binder1st.
|
||||
*
|
||||
* The type @c binder2nd and its creator function @c bind2nd do the same
|
||||
* thing, but the stored argument is passed as the second parameter instead
|
||||
* of the first, e.g., @c bind2nd(std::minus<float>(),1.3) will create a
|
||||
* functor whose @c operator() accepts a floating-point number, subtracts
|
||||
* 1.3 from it, and returns the result. (If @c bind1st had been used,
|
||||
* the functor would perform <em>1.3 - x</em> instead.
|
||||
*
|
||||
* Creator-wrapper functions like @c bind1st are intended to be used in
|
||||
* calling algorithms. Their return values will be temporary objects.
|
||||
* (The goal is to not require you to type names like
|
||||
* @c std::binder1st<std::plus<int>> for declaring a variable to hold the
|
||||
* return value from @c bind1st(std::plus<int>(),5).
|
||||
*
|
||||
* These become more useful when combined with the composition functions.
|
||||
*
|
||||
* These functions are deprecated in C++11 and can be replaced by
|
||||
* @c std::bind (or @c std::tr1::bind) which is more powerful and flexible,
|
||||
* supporting functions with any number of arguments. Uses of @c bind1st
|
||||
* can be replaced by @c std::bind(f, x, std::placeholders::_1) and
|
||||
* @c bind2nd by @c std::bind(f, std::placeholders::_1, x).
|
||||
* @{
|
||||
*/
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation>
|
||||
class binder1st
|
||||
: public unary_function<typename _Operation::second_argument_type,
|
||||
typename _Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
typename _Operation::first_argument_type value;
|
||||
|
||||
public:
|
||||
binder1st(const _Operation& __x,
|
||||
const typename _Operation::first_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
typename _Operation::result_type
|
||||
operator()(const typename _Operation::second_argument_type& __x) const
|
||||
{ return op(value, __x); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
typename _Operation::result_type
|
||||
operator()(typename _Operation::second_argument_type& __x) const
|
||||
{ return op(value, __x); }
|
||||
} _GLIBCXX_DEPRECATED;
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation, typename _Tp>
|
||||
inline binder1st<_Operation>
|
||||
bind1st(const _Operation& __fn, const _Tp& __x)
|
||||
{
|
||||
typedef typename _Operation::first_argument_type _Arg1_type;
|
||||
return binder1st<_Operation>(__fn, _Arg1_type(__x));
|
||||
}
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation>
|
||||
class binder2nd
|
||||
: public unary_function<typename _Operation::first_argument_type,
|
||||
typename _Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
_Operation op;
|
||||
typename _Operation::second_argument_type value;
|
||||
|
||||
public:
|
||||
binder2nd(const _Operation& __x,
|
||||
const typename _Operation::second_argument_type& __y)
|
||||
: op(__x), value(__y) { }
|
||||
|
||||
typename _Operation::result_type
|
||||
operator()(const typename _Operation::first_argument_type& __x) const
|
||||
{ return op(__x, value); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 109. Missing binders for non-const sequence elements
|
||||
typename _Operation::result_type
|
||||
operator()(typename _Operation::first_argument_type& __x) const
|
||||
{ return op(__x, value); }
|
||||
} _GLIBCXX_DEPRECATED;
|
||||
|
||||
/// One of the @link binders binder functors@endlink.
|
||||
template<typename _Operation, typename _Tp>
|
||||
inline binder2nd<_Operation>
|
||||
bind2nd(const _Operation& __fn, const _Tp& __x)
|
||||
{
|
||||
typedef typename _Operation::second_argument_type _Arg2_type;
|
||||
return binder2nd<_Operation>(__fn, _Arg2_type(__x));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif /* _BACKWARD_BINDERS_H */
|
||||
|
|
@ -0,0 +1,854 @@
|
|||
// <algorithm> Forward declarations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/algorithmfwd.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{algorithm}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ALGORITHMFWD_H
|
||||
#define _GLIBCXX_ALGORITHMFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../bits/stl_pair.h"
|
||||
#include "../bits/stl_iterator_base_types.h"
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../initializer_list"
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/*
|
||||
adjacent_find
|
||||
all_of (C++11)
|
||||
any_of (C++11)
|
||||
binary_search
|
||||
clamp (C++17)
|
||||
copy
|
||||
copy_backward
|
||||
copy_if (C++11)
|
||||
copy_n (C++11)
|
||||
count
|
||||
count_if
|
||||
equal
|
||||
equal_range
|
||||
fill
|
||||
fill_n
|
||||
find
|
||||
find_end
|
||||
find_first_of
|
||||
find_if
|
||||
find_if_not (C++11)
|
||||
for_each
|
||||
generate
|
||||
generate_n
|
||||
includes
|
||||
inplace_merge
|
||||
is_heap (C++11)
|
||||
is_heap_until (C++11)
|
||||
is_partitioned (C++11)
|
||||
is_sorted (C++11)
|
||||
is_sorted_until (C++11)
|
||||
iter_swap
|
||||
lexicographical_compare
|
||||
lower_bound
|
||||
make_heap
|
||||
max
|
||||
max_element
|
||||
merge
|
||||
min
|
||||
min_element
|
||||
minmax (C++11)
|
||||
minmax_element (C++11)
|
||||
mismatch
|
||||
next_permutation
|
||||
none_of (C++11)
|
||||
nth_element
|
||||
partial_sort
|
||||
partial_sort_copy
|
||||
partition
|
||||
partition_copy (C++11)
|
||||
partition_point (C++11)
|
||||
pop_heap
|
||||
prev_permutation
|
||||
push_heap
|
||||
random_shuffle
|
||||
remove
|
||||
remove_copy
|
||||
remove_copy_if
|
||||
remove_if
|
||||
replace
|
||||
replace_copy
|
||||
replace_copy_if
|
||||
replace_if
|
||||
reverse
|
||||
reverse_copy
|
||||
rotate
|
||||
rotate_copy
|
||||
search
|
||||
search_n
|
||||
set_difference
|
||||
set_intersection
|
||||
set_symmetric_difference
|
||||
set_union
|
||||
shuffle (C++11)
|
||||
sort
|
||||
sort_heap
|
||||
stable_partition
|
||||
stable_sort
|
||||
swap
|
||||
swap_ranges
|
||||
transform
|
||||
unique
|
||||
unique_copy
|
||||
upper_bound
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup algorithms Algorithms
|
||||
*
|
||||
* Components for performing algorithmic operations. Includes
|
||||
* non-modifying sequence, modifying (mutating) sequence, sorting,
|
||||
* searching, merge, partition, heap, set, minima, maxima, and
|
||||
* permutation operations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup mutating_algorithms Mutating
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup non_mutating_algorithms Non-Mutating
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sorting_algorithms Sorting
|
||||
* @ingroup algorithms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup set_algorithms Set Operation
|
||||
* @ingroup sorting_algorithms
|
||||
*
|
||||
* These algorithms are common set operations performed on sequences
|
||||
* that are already sorted. The number of comparisons will be
|
||||
* linear.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup binary_search_algorithms Binary Search
|
||||
* @ingroup sorting_algorithms
|
||||
*
|
||||
* These algorithms are variations of a classic binary search, and
|
||||
* all assume that the sequence being searched is already sorted.
|
||||
*
|
||||
* The number of comparisons will be logarithmic (and as few as
|
||||
* possible). The number of steps through the sequence will be
|
||||
* logarithmic for random-access iterators (e.g., pointers), and
|
||||
* linear otherwise.
|
||||
*
|
||||
* The LWG has passed Defect Report 270, which notes: <em>The
|
||||
* proposed resolution reinterprets binary search. Instead of
|
||||
* thinking about searching for a value in a sorted range, we view
|
||||
* that as an important special case of a more general algorithm:
|
||||
* searching for the partition point in a partitioned range. We
|
||||
* also add a guarantee that the old wording did not: we ensure that
|
||||
* the upper bound is no earlier than the lower bound, that the pair
|
||||
* returned by equal_range is a valid range, and that the first part
|
||||
* of that pair is the lower bound.</em>
|
||||
*
|
||||
* The actual effect of the first sentence is that a comparison
|
||||
* functor passed by the user doesn't necessarily need to induce a
|
||||
* strict weak ordering relation. Rather, it partitions the range.
|
||||
*/
|
||||
|
||||
// adjacent_find
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
bool
|
||||
all_of(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
bool
|
||||
any_of(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
bool
|
||||
binary_search(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
clamp(const _Tp&, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
clamp(const _Tp&, const _Tp&, const _Tp&, _Compare);
|
||||
#endif
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_OIter
|
||||
copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _BIter1, typename _BIter2>
|
||||
_BIter2
|
||||
copy_backward(_BIter1, _BIter1, _BIter2);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _OIter, typename _Predicate>
|
||||
_OIter
|
||||
copy_if(_IIter, _IIter, _OIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Size, typename _OIter>
|
||||
_OIter
|
||||
copy_n(_IIter, _Size, _OIter);
|
||||
#endif
|
||||
|
||||
// count
|
||||
// count_if
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
pair<_FIter, _FIter>
|
||||
equal_range(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
void
|
||||
fill(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Tp>
|
||||
_OIter
|
||||
fill_n(_OIter, _Size, const _Tp&);
|
||||
|
||||
// find
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
// find_first_of
|
||||
// find_if
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_IIter
|
||||
find_if_not(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
// for_each
|
||||
// generate
|
||||
// generate_n
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
bool
|
||||
includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
void
|
||||
inplace_merge(_BIter, _BIter, _BIter, _Compare);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _RAIter>
|
||||
bool
|
||||
is_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
bool
|
||||
is_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
_RAIter
|
||||
is_heap_until(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
_RAIter
|
||||
is_heap_until(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
bool
|
||||
is_partitioned(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
bool
|
||||
is_permutation(_FIter1, _FIter1, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2,
|
||||
typename _BinaryPredicate>
|
||||
bool
|
||||
is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter>
|
||||
bool
|
||||
is_sorted(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
bool
|
||||
is_sorted(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
is_sorted_until(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_FIter
|
||||
is_sorted_until(_FIter, _FIter, _Compare);
|
||||
#endif
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
void
|
||||
iter_swap(_FIter1, _FIter2);
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_FIter
|
||||
lower_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
make_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
make_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
max(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// max_element
|
||||
// merge
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
const _Tp&
|
||||
min(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
// min_element
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<const _Tp&, const _Tp&>
|
||||
minmax(const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<const _Tp&, const _Tp&>
|
||||
minmax(const _Tp&, const _Tp&, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
minmax_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_FIter, _FIter>
|
||||
minmax_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
min(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
min(initializer_list<_Tp>, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
max(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_Tp
|
||||
max(initializer_list<_Tp>, _Compare);
|
||||
|
||||
template<typename _Tp>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_Tp, _Tp>
|
||||
minmax(initializer_list<_Tp>);
|
||||
|
||||
template<typename _Tp, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
pair<_Tp, _Tp>
|
||||
minmax(initializer_list<_Tp>, _Compare);
|
||||
#endif
|
||||
|
||||
// mismatch
|
||||
|
||||
template<typename _BIter>
|
||||
bool
|
||||
next_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
bool
|
||||
next_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _Predicate>
|
||||
bool
|
||||
none_of(_IIter, _IIter, _Predicate);
|
||||
#endif
|
||||
|
||||
// nth_element
|
||||
// partial_sort
|
||||
|
||||
template<typename _IIter, typename _RAIter>
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _IIter, typename _RAIter, typename _Compare>
|
||||
_RAIter
|
||||
partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
// partition
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _IIter, typename _OIter1,
|
||||
typename _OIter2, typename _Predicate>
|
||||
pair<_OIter1, _OIter2>
|
||||
partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate);
|
||||
|
||||
template<typename _FIter, typename _Predicate>
|
||||
_FIter
|
||||
partition_point(_FIter, _FIter, _Predicate);
|
||||
#endif
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
pop_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter>
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _Compare>
|
||||
bool
|
||||
prev_permutation(_BIter, _BIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
push_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
push_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
// random_shuffle
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
remove(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate>
|
||||
_FIter
|
||||
remove_if(_FIter, _FIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_OIter
|
||||
remove_copy(_IIter, _IIter, _OIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Predicate>
|
||||
_OIter
|
||||
remove_copy_if(_IIter, _IIter, _OIter, _Predicate);
|
||||
|
||||
// replace
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _Tp>
|
||||
_OIter
|
||||
replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp>
|
||||
_OIter
|
||||
replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&);
|
||||
|
||||
// replace_if
|
||||
|
||||
template<typename _BIter>
|
||||
void
|
||||
reverse(_BIter, _BIter);
|
||||
|
||||
template<typename _BIter, typename _OIter>
|
||||
_OIter
|
||||
reverse_copy(_BIter, _BIter, _OIter);
|
||||
|
||||
inline namespace _V2
|
||||
{
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
rotate(_FIter, _FIter, _FIter);
|
||||
}
|
||||
|
||||
template<typename _FIter, typename _OIter>
|
||||
_OIter
|
||||
rotate_copy(_FIter, _FIter, _FIter, _OIter);
|
||||
|
||||
// search
|
||||
// search_n
|
||||
// set_difference
|
||||
// set_intersection
|
||||
// set_symmetric_difference
|
||||
// set_union
|
||||
|
||||
#if (__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
|
||||
template<typename _RAIter, typename _UGenerator>
|
||||
void
|
||||
shuffle(_RAIter, _RAIter, _UGenerator&&);
|
||||
#endif
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
sort_heap(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_BIter
|
||||
stable_partition(_BIter, _BIter, _Predicate);
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// For C++11 swap() is declared in <type_traits>.
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline void
|
||||
swap(_Tp& __a, _Tp& __b);
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline void
|
||||
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]);
|
||||
#endif
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter2
|
||||
swap_ranges(_FIter1, _FIter1, _FIter2);
|
||||
|
||||
// transform
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
unique(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_FIter
|
||||
unique(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
// unique_copy
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Tp, typename _Compare>
|
||||
_FIter
|
||||
upper_bound(_FIter, _FIter, const _Tp&, _Compare);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_ALGO
|
||||
|
||||
template<typename _FIter>
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _BinaryPredicate>
|
||||
_FIter
|
||||
adjacent_find(_FIter, _FIter, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
typename iterator_traits<_IIter>::difference_type
|
||||
count_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
bool
|
||||
equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Tp>
|
||||
_IIter
|
||||
find(_IIter, _IIter, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter, typename _Predicate>
|
||||
_IIter
|
||||
find_if(_IIter, _IIter, _Predicate);
|
||||
|
||||
template<typename _IIter, typename _Funct>
|
||||
_Funct
|
||||
for_each(_IIter, _IIter, _Funct);
|
||||
|
||||
template<typename _FIter, typename _Generator>
|
||||
void
|
||||
generate(_FIter, _FIter, _Generator);
|
||||
|
||||
template<typename _OIter, typename _Size, typename _Generator>
|
||||
_OIter
|
||||
generate_n(_OIter, _Size, _Generator);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _Compare>
|
||||
bool
|
||||
lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
max_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
max_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _FIter>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
min_element(_FIter, _FIter);
|
||||
|
||||
template<typename _FIter, typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
_FIter
|
||||
min_element(_FIter, _FIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2>
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
|
||||
pair<_IIter1, _IIter2>
|
||||
mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
nth_element(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
partial_sort(_RAIter, _RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _BIter, typename _Predicate>
|
||||
_BIter
|
||||
partition(_BIter, _BIter, _Predicate);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Generator>
|
||||
void
|
||||
random_shuffle(_RAIter, _RAIter,
|
||||
#if __cplusplus >= 201103L
|
||||
_Generator&&);
|
||||
#else
|
||||
_Generator&);
|
||||
#endif
|
||||
|
||||
template<typename _FIter, typename _Tp>
|
||||
void
|
||||
replace(_FIter, _FIter, const _Tp&, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Predicate, typename _Tp>
|
||||
void
|
||||
replace_if(_FIter, _FIter, _Predicate, const _Tp&);
|
||||
|
||||
template<typename _FIter1, typename _FIter2>
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2);
|
||||
|
||||
template<typename _FIter1, typename _FIter2, typename _BinaryPredicate>
|
||||
_FIter1
|
||||
search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp>
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&);
|
||||
|
||||
template<typename _FIter, typename _Size, typename _Tp,
|
||||
typename _BinaryPredicate>
|
||||
_FIter
|
||||
search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2,
|
||||
_OIter, _Compare);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter>
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _Compare>
|
||||
_OIter
|
||||
set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _RAIter>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter);
|
||||
|
||||
template<typename _RAIter, typename _Compare>
|
||||
void
|
||||
stable_sort(_RAIter, _RAIter, _Compare);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _UnaryOperation>
|
||||
_OIter
|
||||
transform(_IIter, _IIter, _OIter, _UnaryOperation);
|
||||
|
||||
template<typename _IIter1, typename _IIter2, typename _OIter,
|
||||
typename _BinaryOperation>
|
||||
_OIter
|
||||
transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation);
|
||||
|
||||
template<typename _IIter, typename _OIter>
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter);
|
||||
|
||||
template<typename _IIter, typename _OIter, typename _BinaryPredicate>
|
||||
_OIter
|
||||
unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_ALGO
|
||||
} // namespace std
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/algorithmfwd.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,605 @@
|
|||
// Allocator traits -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/alloc_traits.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _ALLOC_TRAITS_H
|
||||
#define _ALLOC_TRAITS_H 1
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
#include "../bits/memoryfwd.h"
|
||||
#include "../bits/ptr_traits.h"
|
||||
#include "../ext/numeric_traits.h"
|
||||
|
||||
#define __cpp_lib_allocator_traits_is_always_equal 201411
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct __allocator_traits_base
|
||||
{
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __rebind : __replace_first_arg<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __rebind<_Tp, _Up,
|
||||
__void_t<typename _Tp::template rebind<_Up>::other>>
|
||||
{ using type = typename _Tp::template rebind<_Up>::other; };
|
||||
|
||||
protected:
|
||||
template<typename _Tp>
|
||||
using __pointer = typename _Tp::pointer;
|
||||
template<typename _Tp>
|
||||
using __c_pointer = typename _Tp::const_pointer;
|
||||
template<typename _Tp>
|
||||
using __v_pointer = typename _Tp::void_pointer;
|
||||
template<typename _Tp>
|
||||
using __cv_pointer = typename _Tp::const_void_pointer;
|
||||
template<typename _Tp>
|
||||
using __pocca = typename _Tp::propagate_on_container_copy_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocma = typename _Tp::propagate_on_container_move_assignment;
|
||||
template<typename _Tp>
|
||||
using __pocs = typename _Tp::propagate_on_container_swap;
|
||||
template<typename _Tp>
|
||||
using __equal = typename _Tp::is_always_equal;
|
||||
};
|
||||
|
||||
template<typename _Alloc, typename _Up>
|
||||
using __alloc_rebind
|
||||
= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
|
||||
|
||||
/**
|
||||
* @brief Uniform interface to all allocator types.
|
||||
* @ingroup allocators
|
||||
*/
|
||||
template<typename _Alloc>
|
||||
struct allocator_traits : __allocator_traits_base
|
||||
{
|
||||
/// The allocator type
|
||||
typedef _Alloc allocator_type;
|
||||
/// The allocated type
|
||||
typedef typename _Alloc::value_type value_type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's pointer type.
|
||||
*
|
||||
* @c Alloc::pointer if that type exists, otherwise @c value_type*
|
||||
*/
|
||||
using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
|
||||
|
||||
private:
|
||||
// Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
|
||||
template<template<typename> class _Func, typename _Tp, typename = void>
|
||||
struct _Ptr
|
||||
{
|
||||
using type = typename pointer_traits<pointer>::template rebind<_Tp>;
|
||||
};
|
||||
|
||||
template<template<typename> class _Func, typename _Tp>
|
||||
struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
|
||||
{
|
||||
using type = _Func<_Alloc>;
|
||||
};
|
||||
|
||||
// Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
|
||||
template<typename _A2, typename _PtrT, typename = void>
|
||||
struct _Diff
|
||||
{ using type = typename pointer_traits<_PtrT>::difference_type; };
|
||||
|
||||
template<typename _A2, typename _PtrT>
|
||||
struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
|
||||
{ using type = typename _A2::difference_type; };
|
||||
|
||||
// Select _A2::size_type or make_unsigned<_DiffT>::type
|
||||
template<typename _A2, typename _DiffT, typename = void>
|
||||
struct _Size : make_unsigned<_DiffT> { };
|
||||
|
||||
template<typename _A2, typename _DiffT>
|
||||
struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
|
||||
{ using type = typename _A2::size_type; };
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The allocator's const pointer type.
|
||||
*
|
||||
* @c Alloc::const_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
|
||||
*/
|
||||
using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's void pointer type.
|
||||
*
|
||||
* @c Alloc::void_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<void> </tt>
|
||||
*/
|
||||
using void_pointer = typename _Ptr<__v_pointer, void>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's const void pointer type.
|
||||
*
|
||||
* @c Alloc::const_void_pointer if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::rebind<const void> </tt>
|
||||
*/
|
||||
using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's difference type
|
||||
*
|
||||
* @c Alloc::difference_type if that type exists, otherwise
|
||||
* <tt> pointer_traits<pointer>::difference_type </tt>
|
||||
*/
|
||||
using difference_type = typename _Diff<_Alloc, pointer>::type;
|
||||
|
||||
/**
|
||||
* @brief The allocator's size type
|
||||
*
|
||||
* @c Alloc::size_type if that type exists, otherwise
|
||||
* <tt> make_unsigned<difference_type>::type </tt>
|
||||
*/
|
||||
using size_type = typename _Size<_Alloc, difference_type>::type;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on copy assignment
|
||||
*
|
||||
* @c Alloc::propagate_on_container_copy_assignment if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_copy_assignment
|
||||
= __detected_or_t<false_type, __pocca, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on move assignment
|
||||
*
|
||||
* @c Alloc::propagate_on_container_move_assignment if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_move_assignment
|
||||
= __detected_or_t<false_type, __pocma, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief How the allocator is propagated on swap
|
||||
*
|
||||
* @c Alloc::propagate_on_container_swap if that type exists,
|
||||
* otherwise @c false_type
|
||||
*/
|
||||
using propagate_on_container_swap
|
||||
= __detected_or_t<false_type, __pocs, _Alloc>;
|
||||
|
||||
/**
|
||||
* @brief Whether all instances of the allocator type compare equal.
|
||||
*
|
||||
* @c Alloc::is_always_equal if that type exists,
|
||||
* otherwise @c is_empty<Alloc>::type
|
||||
*/
|
||||
using is_always_equal
|
||||
= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
|
||||
|
||||
template<typename _Tp>
|
||||
using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
|
||||
template<typename _Tp>
|
||||
using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
|
||||
|
||||
private:
|
||||
template<typename _Alloc2>
|
||||
static auto
|
||||
_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
|
||||
-> decltype(__a.allocate(__n, __hint))
|
||||
{ return __a.allocate(__n, __hint); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static pointer
|
||||
_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __construct_helper
|
||||
{
|
||||
template<typename _Alloc2,
|
||||
typename = decltype(std::declval<_Alloc2*>()->construct(
|
||||
std::declval<_Tp*>(), std::declval<_Args>()...))>
|
||||
static true_type __test(int);
|
||||
|
||||
template<typename>
|
||||
static false_type __test(...);
|
||||
|
||||
using type = decltype(__test<_Alloc>(0));
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
using __has_construct
|
||||
= typename __construct_helper<_Tp, _Args...>::type;
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
static _Require<__has_construct<_Tp, _Args...>>
|
||||
_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
|
||||
{ __a.construct(__p, std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
static
|
||||
_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
|
||||
is_constructible<_Tp, _Args...>>>
|
||||
_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
|
||||
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static auto
|
||||
_S_destroy(_Alloc2& __a, _Tp* __p, int)
|
||||
-> decltype(__a.destroy(__p))
|
||||
{ __a.destroy(__p); }
|
||||
|
||||
template<typename _Alloc2, typename _Tp>
|
||||
static void
|
||||
_S_destroy(_Alloc2&, _Tp* __p, ...)
|
||||
{ __p->~_Tp(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static auto
|
||||
_S_max_size(_Alloc2& __a, int)
|
||||
-> decltype(__a.max_size())
|
||||
{ return __a.max_size(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static size_type
|
||||
_S_max_size(_Alloc2&, ...)
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2466. allocator_traits::max_size() default behavior is incorrect
|
||||
return __gnu_cxx::__numeric_traits<size_type>::__max
|
||||
/ sizeof(value_type);
|
||||
}
|
||||
|
||||
template<typename _Alloc2>
|
||||
static auto
|
||||
_S_select(_Alloc2& __a, int)
|
||||
-> decltype(__a.select_on_container_copy_construction())
|
||||
{ return __a.select_on_container_copy_construction(); }
|
||||
|
||||
template<typename _Alloc2>
|
||||
static _Alloc2
|
||||
_S_select(_Alloc2& __a, ...)
|
||||
{ return __a; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
*
|
||||
* Calls @c a.allocate(n)
|
||||
*/
|
||||
static pointer
|
||||
allocate(_Alloc& __a, size_type __n)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
* @param __hint Aid to locality.
|
||||
* @return Memory of suitable size and alignment for @a n objects
|
||||
* of type @c value_type
|
||||
*
|
||||
* Returns <tt> a.allocate(n, hint) </tt> if that expression is
|
||||
* well-formed, otherwise returns @c a.allocate(n)
|
||||
*/
|
||||
static pointer
|
||||
allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
|
||||
{ return _S_allocate(__a, __n, __hint, 0); }
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the memory to deallocate.
|
||||
* @param __n The number of objects space was allocated for.
|
||||
*
|
||||
* Calls <tt> a.deallocate(p, n) </tt>
|
||||
*/
|
||||
static void
|
||||
deallocate(_Alloc& __a, pointer __p, size_type __n)
|
||||
{ __a.deallocate(__p, __n); }
|
||||
|
||||
/**
|
||||
* @brief Construct an object of type @a _Tp
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to memory of suitable size and alignment for Tp
|
||||
* @param __args Constructor arguments.
|
||||
*
|
||||
* Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
|
||||
* if that expression is well-formed, otherwise uses placement-new
|
||||
* to construct an object of type @a _Tp at location @a __p from the
|
||||
* arguments @a __args...
|
||||
*/
|
||||
template<typename _Tp, typename... _Args>
|
||||
static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
|
||||
-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
|
||||
{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
|
||||
|
||||
/**
|
||||
* @brief Destroy an object of type @a _Tp
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the object to destroy
|
||||
*
|
||||
* Calls @c __a.destroy(__p) if that expression is well-formed,
|
||||
* otherwise calls @c __p->~_Tp()
|
||||
*/
|
||||
template<typename _Tp>
|
||||
static void destroy(_Alloc& __a, _Tp* __p)
|
||||
{ _S_destroy(__a, __p, 0); }
|
||||
|
||||
/**
|
||||
* @brief The maximum supported allocation size
|
||||
* @param __a An allocator.
|
||||
* @return @c __a.max_size() or @c numeric_limits<size_type>::max()
|
||||
*
|
||||
* Returns @c __a.max_size() if that expression is well-formed,
|
||||
* otherwise returns @c numeric_limits<size_type>::max()
|
||||
*/
|
||||
static size_type max_size(const _Alloc& __a) noexcept
|
||||
{ return _S_max_size(__a, 0); }
|
||||
|
||||
/**
|
||||
* @brief Obtain an allocator to use when copying a container.
|
||||
* @param __rhs An allocator.
|
||||
* @return @c __rhs.select_on_container_copy_construction() or @a __rhs
|
||||
*
|
||||
* Returns @c __rhs.select_on_container_copy_construction() if that
|
||||
* expression is well-formed, otherwise returns @a __rhs
|
||||
*/
|
||||
static _Alloc
|
||||
select_on_container_copy_construction(const _Alloc& __rhs)
|
||||
{ return _S_select(__rhs, 0); }
|
||||
};
|
||||
|
||||
/// Partial specialization for std::allocator.
|
||||
template<typename _Tp>
|
||||
struct allocator_traits<allocator<_Tp>>
|
||||
{
|
||||
/// The allocator type
|
||||
using allocator_type = allocator<_Tp>;
|
||||
/// The allocated type
|
||||
using value_type = _Tp;
|
||||
|
||||
/// The allocator's pointer type.
|
||||
using pointer = _Tp*;
|
||||
|
||||
/// The allocator's const pointer type.
|
||||
using const_pointer = const _Tp*;
|
||||
|
||||
/// The allocator's void pointer type.
|
||||
using void_pointer = void*;
|
||||
|
||||
/// The allocator's const void pointer type.
|
||||
using const_void_pointer = const void*;
|
||||
|
||||
/// The allocator's difference type
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
/// The allocator's size type
|
||||
using size_type = std::size_t;
|
||||
|
||||
/// How the allocator is propagated on copy assignment
|
||||
using propagate_on_container_copy_assignment = false_type;
|
||||
|
||||
/// How the allocator is propagated on move assignment
|
||||
using propagate_on_container_move_assignment = true_type;
|
||||
|
||||
/// How the allocator is propagated on swap
|
||||
using propagate_on_container_swap = false_type;
|
||||
|
||||
/// Whether all instances of the allocator type compare equal.
|
||||
using is_always_equal = true_type;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_alloc = allocator<_Up>;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind_traits = allocator_traits<allocator<_Up>>;
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
*
|
||||
* Calls @c a.allocate(n)
|
||||
*/
|
||||
static pointer
|
||||
allocate(allocator_type& __a, size_type __n)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
/**
|
||||
* @brief Allocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __n The number of objects to allocate space for.
|
||||
* @param __hint Aid to locality.
|
||||
* @return Memory of suitable size and alignment for @a n objects
|
||||
* of type @c value_type
|
||||
*
|
||||
* Returns <tt> a.allocate(n, hint) </tt>
|
||||
*/
|
||||
static pointer
|
||||
allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
|
||||
{ return __a.allocate(__n, __hint); }
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory.
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the memory to deallocate.
|
||||
* @param __n The number of objects space was allocated for.
|
||||
*
|
||||
* Calls <tt> a.deallocate(p, n) </tt>
|
||||
*/
|
||||
static void
|
||||
deallocate(allocator_type& __a, pointer __p, size_type __n)
|
||||
{ __a.deallocate(__p, __n); }
|
||||
|
||||
/**
|
||||
* @brief Construct an object of type @a _Up
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to memory of suitable size and alignment for Tp
|
||||
* @param __args Constructor arguments.
|
||||
*
|
||||
* Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
|
||||
*/
|
||||
template<typename _Up, typename... _Args>
|
||||
static void
|
||||
construct(allocator_type& __a, _Up* __p, _Args&&... __args)
|
||||
{ __a.construct(__p, std::forward<_Args>(__args)...); }
|
||||
|
||||
/**
|
||||
* @brief Destroy an object of type @a _Up
|
||||
* @param __a An allocator.
|
||||
* @param __p Pointer to the object to destroy
|
||||
*
|
||||
* Calls @c __a.destroy(__p).
|
||||
*/
|
||||
template<typename _Up>
|
||||
static void
|
||||
destroy(allocator_type& __a, _Up* __p)
|
||||
{ __a.destroy(__p); }
|
||||
|
||||
/**
|
||||
* @brief The maximum supported allocation size
|
||||
* @param __a An allocator.
|
||||
* @return @c __a.max_size()
|
||||
*/
|
||||
static size_type
|
||||
max_size(const allocator_type& __a) noexcept
|
||||
{ return __a.max_size(); }
|
||||
|
||||
/**
|
||||
* @brief Obtain an allocator to use when copying a container.
|
||||
* @param __rhs An allocator.
|
||||
* @return @c __rhs
|
||||
*/
|
||||
static allocator_type
|
||||
select_on_container_copy_construction(const allocator_type& __rhs)
|
||||
{ return __rhs; }
|
||||
};
|
||||
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void
|
||||
__do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
|
||||
{ __one = __two; }
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void
|
||||
__do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
|
||||
{ }
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
|
||||
{
|
||||
typedef allocator_traits<_Alloc> __traits;
|
||||
typedef typename __traits::propagate_on_container_copy_assignment __pocca;
|
||||
__do_alloc_on_copy(__one, __two, __pocca());
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
inline _Alloc __alloc_on_copy(const _Alloc& __a)
|
||||
{
|
||||
typedef allocator_traits<_Alloc> __traits;
|
||||
return __traits::select_on_container_copy_construction(__a);
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
|
||||
{ __one = std::move(__two); }
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
|
||||
{ }
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __alloc_on_move(_Alloc& __one, _Alloc& __two)
|
||||
{
|
||||
typedef allocator_traits<_Alloc> __traits;
|
||||
typedef typename __traits::propagate_on_container_move_assignment __pocma;
|
||||
__do_alloc_on_move(__one, __two, __pocma());
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
|
||||
{
|
||||
using std::swap;
|
||||
swap(__one, __two);
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
|
||||
{ }
|
||||
|
||||
template<typename _Alloc>
|
||||
inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two)
|
||||
{
|
||||
typedef allocator_traits<_Alloc> __traits;
|
||||
typedef typename __traits::propagate_on_container_swap __pocs;
|
||||
__do_alloc_on_swap(__one, __two, __pocs());
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
class __is_copy_insertable_impl
|
||||
{
|
||||
typedef allocator_traits<_Alloc> _Traits;
|
||||
|
||||
template<typename _Up, typename
|
||||
= decltype(_Traits::construct(std::declval<_Alloc&>(),
|
||||
std::declval<_Up*>(),
|
||||
std::declval<const _Up&>()))>
|
||||
static true_type
|
||||
_M_select(int);
|
||||
|
||||
template<typename _Up>
|
||||
static false_type
|
||||
_M_select(...);
|
||||
|
||||
public:
|
||||
typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
|
||||
};
|
||||
|
||||
// true if _Alloc::value_type is CopyInsertable into containers using _Alloc
|
||||
template<typename _Alloc>
|
||||
struct __is_copy_insertable
|
||||
: __is_copy_insertable_impl<_Alloc>::type
|
||||
{ };
|
||||
|
||||
// std::allocator<_Tp> just requires CopyConstructible
|
||||
template<typename _Tp>
|
||||
struct __is_copy_insertable<allocator<_Tp>>
|
||||
: is_copy_constructible<_Tp>
|
||||
{ };
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
// Allocators -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2015 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/allocator.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _ALLOCATOR_H
|
||||
#define _ALLOCATOR_H 1
|
||||
|
||||
#include "../bits/c++allocator.h" // Define the base class to std::allocator.
|
||||
#include "../bits/memoryfwd.h"
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../type_traits"
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup allocators
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// allocator<void> specialization.
|
||||
template<>
|
||||
class allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef void* pointer;
|
||||
typedef const void* const_pointer;
|
||||
typedef void value_type;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef allocator<_Tp1> other; };
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. std::allocator propagate_on_container_move_assignment
|
||||
typedef true_type propagate_on_container_move_assignment;
|
||||
|
||||
template<typename _Up, typename... _Args>
|
||||
void
|
||||
construct(_Up* __p, _Args&&... __args)
|
||||
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
destroy(_Up* __p) { __p->~_Up(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The @a standard allocator, as per [20.4].
|
||||
*
|
||||
* See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator
|
||||
* for further details.
|
||||
*
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class allocator: public __allocator_base<_Tp>
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef _Tp* pointer;
|
||||
typedef const _Tp* const_pointer;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
typedef _Tp value_type;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef allocator<_Tp1> other; };
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. std::allocator propagate_on_container_move_assignment
|
||||
typedef true_type propagate_on_container_move_assignment;
|
||||
#endif
|
||||
|
||||
allocator() throw() { }
|
||||
|
||||
allocator(const allocator& __a) throw()
|
||||
: __allocator_base<_Tp>(__a) { }
|
||||
|
||||
template<typename _Tp1>
|
||||
allocator(const allocator<_Tp1>&) throw() { }
|
||||
|
||||
~allocator() throw() { }
|
||||
|
||||
// Inherit everything else.
|
||||
};
|
||||
|
||||
template<typename _T1, typename _T2>
|
||||
inline bool
|
||||
operator==(const allocator<_T1>&, const allocator<_T2>&)
|
||||
_GLIBCXX_USE_NOEXCEPT
|
||||
{ return true; }
|
||||
|
||||
template<typename _Tp>
|
||||
inline bool
|
||||
operator==(const allocator<_Tp>&, const allocator<_Tp>&)
|
||||
_GLIBCXX_USE_NOEXCEPT
|
||||
{ return true; }
|
||||
|
||||
template<typename _T1, typename _T2>
|
||||
inline bool
|
||||
operator!=(const allocator<_T1>&, const allocator<_T2>&)
|
||||
_GLIBCXX_USE_NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
template<typename _Tp>
|
||||
inline bool
|
||||
operator!=(const allocator<_Tp>&, const allocator<_Tp>&)
|
||||
_GLIBCXX_USE_NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
/// @} group allocator
|
||||
|
||||
// Inhibit implicit instantiations for required instantiations,
|
||||
// which are defined via explicit instantiations elsewhere.
|
||||
#if _GLIBCXX_EXTERN_TEMPLATE
|
||||
extern template class allocator<char>;
|
||||
extern template class allocator<wchar_t>;
|
||||
#endif
|
||||
|
||||
// Undefine.
|
||||
#undef __allocator_base
|
||||
|
||||
// To implement Option 3 of DR 431.
|
||||
template<typename _Alloc, bool = __is_empty(_Alloc)>
|
||||
struct __alloc_swap
|
||||
{ static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __alloc_swap<_Alloc, false>
|
||||
{
|
||||
static void
|
||||
_S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
|
||||
{
|
||||
// Precondition: swappable allocators.
|
||||
if (__one != __two)
|
||||
swap(__one, __two);
|
||||
}
|
||||
};
|
||||
|
||||
// Optimize for stateless allocators.
|
||||
template<typename _Alloc, bool = __is_empty(_Alloc)>
|
||||
struct __alloc_neq
|
||||
{
|
||||
static bool
|
||||
_S_do_it(const _Alloc&, const _Alloc&)
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __alloc_neq<_Alloc, false>
|
||||
{
|
||||
static bool
|
||||
_S_do_it(const _Alloc& __one, const _Alloc& __two)
|
||||
{ return __one != __two; }
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, bool
|
||||
= __or_<is_copy_constructible<typename _Tp::value_type>,
|
||||
is_nothrow_move_constructible<typename _Tp::value_type>>::value>
|
||||
struct __shrink_to_fit_aux
|
||||
{ static bool _S_do_it(_Tp&) noexcept { return false; } };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __shrink_to_fit_aux<_Tp, true>
|
||||
{
|
||||
static bool
|
||||
_S_do_it(_Tp& __c) noexcept
|
||||
{
|
||||
#if __cpp_exceptions
|
||||
try
|
||||
{
|
||||
_Tp(__make_move_if_noexcept_iterator(__c.begin()),
|
||||
__make_move_if_noexcept_iterator(__c.end()),
|
||||
__c.get_allocator()).swap(__c);
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{ return false; }
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,788 @@
|
|||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
//
|
||||
|
||||
/** @file bits/boost_concept_check.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
// GCC Note: based on version 1.12.0 of the Boost library.
|
||||
|
||||
#ifndef _BOOST_CONCEPT_CHECK_H
|
||||
#define _BOOST_CONCEPT_CHECK_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../bits/stl_iterator_base_types.h" // for traits and tags
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#define _IsUnused __attribute__ ((__unused__))
|
||||
|
||||
// When the C-C code is in use, we would like this function to do as little
|
||||
// as possible at runtime, use as few resources as possible, and hopefully
|
||||
// be elided out of existence... hmmm.
|
||||
template <class _Concept>
|
||||
inline void __function_requires()
|
||||
{
|
||||
void (_Concept::*__x)() _IsUnused = &_Concept::__constraints;
|
||||
}
|
||||
|
||||
// No definition: if this is referenced, there's a problem with
|
||||
// the instantiating type not being one of the required integer types.
|
||||
// Unfortunately, this results in a link-time error, not a compile-time error.
|
||||
void __error_type_must_be_an_integer_type();
|
||||
void __error_type_must_be_an_unsigned_integer_type();
|
||||
void __error_type_must_be_a_signed_integer_type();
|
||||
|
||||
// ??? Should the "concept_checking*" structs begin with more than _ ?
|
||||
#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \
|
||||
template <_func##_type_var##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var##_concept { }; \
|
||||
typedef _concept_checking##_type_var##_concept< \
|
||||
&_ns::_concept <_type_var>::__constraints> \
|
||||
_concept_checking_typedef##_type_var##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept
|
||||
|
||||
#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \
|
||||
typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \
|
||||
template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \
|
||||
struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \
|
||||
typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \
|
||||
&_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \
|
||||
_concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept
|
||||
|
||||
|
||||
template <class _Tp1, class _Tp2>
|
||||
struct _Aux_require_same { };
|
||||
|
||||
template <class _Tp>
|
||||
struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
|
||||
|
||||
template <class _Tp1, class _Tp2>
|
||||
struct _SameTypeConcept
|
||||
{
|
||||
void __constraints() {
|
||||
typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _IntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_an_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _IntegerConcept<short> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned short> { void __constraints(){} };
|
||||
template <> struct _IntegerConcept<int> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned int> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<long long> { void __constraints() {} };
|
||||
template <> struct _IntegerConcept<unsigned long long>
|
||||
{ void __constraints() {} };
|
||||
|
||||
template <class _Tp>
|
||||
struct _SignedIntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_a_signed_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _SignedIntegerConcept<short> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<int> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<long> { void __constraints() {} };
|
||||
template <> struct _SignedIntegerConcept<long long> { void __constraints(){}};
|
||||
|
||||
template <class _Tp>
|
||||
struct _UnsignedIntegerConcept {
|
||||
void __constraints() {
|
||||
__error_type_must_be_an_unsigned_integer_type();
|
||||
}
|
||||
};
|
||||
template <> struct _UnsignedIntegerConcept<unsigned short>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned int>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned long>
|
||||
{ void __constraints() {} };
|
||||
template <> struct _UnsignedIntegerConcept<unsigned long long>
|
||||
{ void __constraints() {} };
|
||||
|
||||
//===========================================================================
|
||||
// Basic Concepts
|
||||
|
||||
template <class _Tp>
|
||||
struct _DefaultConstructibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __a _IsUnused; // require default constructor
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _AssignableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__a = __a; // require assignment operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __b) {
|
||||
__a = __b; // const required for argument to assignment
|
||||
}
|
||||
_Tp __a;
|
||||
// possibly should be "Tp* a;" and then dereference "a" in constraint
|
||||
// functions? present way would require a default ctor, i think...
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _CopyConstructibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __a(__b); // require copy constructor
|
||||
_Tp* __ptr _IsUnused = &__a; // require address of operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __a) {
|
||||
_Tp __c _IsUnused(__a); // require const copy constructor
|
||||
const _Tp* __ptr _IsUnused = &__a; // require const address of operator
|
||||
}
|
||||
_Tp __b;
|
||||
};
|
||||
|
||||
// The SGI STL version of Assignable requires copy constructor and operator=
|
||||
template <class _Tp>
|
||||
struct _SGIAssignableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_Tp __b _IsUnused(__a);
|
||||
__a = __a; // require assignment operator
|
||||
__const_constraints(__a);
|
||||
}
|
||||
void __const_constraints(const _Tp& __b) {
|
||||
_Tp __c _IsUnused(__b);
|
||||
__a = __b; // const required for argument to assignment
|
||||
}
|
||||
_Tp __a;
|
||||
};
|
||||
|
||||
template <class _From, class _To>
|
||||
struct _ConvertibleConcept
|
||||
{
|
||||
void __constraints() {
|
||||
_To __y _IsUnused = __x;
|
||||
}
|
||||
_From __x;
|
||||
};
|
||||
|
||||
// The C++ standard requirements for many concepts talk about return
|
||||
// types that must be "convertible to bool". The problem with this
|
||||
// requirement is that it leaves the door open for evil proxies that
|
||||
// define things like operator|| with strange return types. Two
|
||||
// possible solutions are:
|
||||
// 1) require the return type to be exactly bool
|
||||
// 2) stay with convertible to bool, and also
|
||||
// specify stuff about all the logical operators.
|
||||
// For now we just test for convertible to bool.
|
||||
template <class _Tp>
|
||||
void __aux_require_boolean_expr(const _Tp& __t) {
|
||||
bool __x _IsUnused = __t;
|
||||
}
|
||||
|
||||
// FIXME
|
||||
template <class _Tp>
|
||||
struct _EqualityComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a == __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _LessThanComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a < __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
// This is equivalent to SGI STL's LessThanComparable.
|
||||
template <class _Tp>
|
||||
struct _ComparableConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__a < __b);
|
||||
__aux_require_boolean_expr(__a > __b);
|
||||
__aux_require_boolean_expr(__a <= __b);
|
||||
__aux_require_boolean_expr(__a >= __b);
|
||||
}
|
||||
_Tp __a, __b;
|
||||
};
|
||||
|
||||
#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \
|
||||
template <class _First, class _Second> \
|
||||
struct _NAME { \
|
||||
void __constraints() { (void)__constraints_(); } \
|
||||
bool __constraints_() { \
|
||||
return __a _OP __b; \
|
||||
} \
|
||||
_First __a; \
|
||||
_Second __b; \
|
||||
}
|
||||
|
||||
#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \
|
||||
template <class _Ret, class _First, class _Second> \
|
||||
struct _NAME { \
|
||||
void __constraints() { (void)__constraints_(); } \
|
||||
_Ret __constraints_() { \
|
||||
return __a _OP __b; \
|
||||
} \
|
||||
_First __a; \
|
||||
_Second __b; \
|
||||
}
|
||||
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept);
|
||||
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept);
|
||||
_GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept);
|
||||
|
||||
#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT
|
||||
#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT
|
||||
|
||||
//===========================================================================
|
||||
// Function Object Concepts
|
||||
|
||||
template <class _Func, class _Return>
|
||||
struct _GeneratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
const _Return& __r _IsUnused = __f();// require operator() member function
|
||||
}
|
||||
_Func __f;
|
||||
};
|
||||
|
||||
|
||||
template <class _Func>
|
||||
struct _GeneratorConcept<_Func,void>
|
||||
{
|
||||
void __constraints() {
|
||||
__f(); // require operator() member function
|
||||
}
|
||||
_Func __f;
|
||||
};
|
||||
|
||||
template <class _Func, class _Return, class _Arg>
|
||||
struct _UnaryFunctionConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__r = __f(__arg); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
_Return __r;
|
||||
};
|
||||
|
||||
template <class _Func, class _Arg>
|
||||
struct _UnaryFunctionConcept<_Func, void, _Arg> {
|
||||
void __constraints() {
|
||||
__f(__arg); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
};
|
||||
|
||||
template <class _Func, class _Return, class _First, class _Second>
|
||||
struct _BinaryFunctionConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__r = __f(__first, __second); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_First __first;
|
||||
_Second __second;
|
||||
_Return __r;
|
||||
};
|
||||
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _BinaryFunctionConcept<_Func, void, _First, _Second>
|
||||
{
|
||||
void __constraints() {
|
||||
__f(__first, __second); // require operator()
|
||||
}
|
||||
_Func __f;
|
||||
_First __first;
|
||||
_Second __second;
|
||||
};
|
||||
|
||||
template <class _Func, class _Arg>
|
||||
struct _UnaryPredicateConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__f(__arg)); // require op() returning bool
|
||||
}
|
||||
_Func __f;
|
||||
_Arg __arg;
|
||||
};
|
||||
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _BinaryPredicateConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool
|
||||
}
|
||||
_Func __f;
|
||||
_First __a;
|
||||
_Second __b;
|
||||
};
|
||||
|
||||
// use this when functor is used inside a container class like std::set
|
||||
template <class _Func, class _First, class _Second>
|
||||
struct _Const_BinaryPredicateConcept {
|
||||
void __constraints() {
|
||||
__const_constraints(__f);
|
||||
}
|
||||
void __const_constraints(const _Func& __fun) {
|
||||
__function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >();
|
||||
// operator() must be a const member function
|
||||
__aux_require_boolean_expr(__fun(__a, __b));
|
||||
}
|
||||
_Func __f;
|
||||
_First __a;
|
||||
_Second __b;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Iterator Concepts
|
||||
|
||||
template <class _Tp>
|
||||
struct _TrivialIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
// __function_requires< _DefaultConstructibleConcept<_Tp> >();
|
||||
__function_requires< _AssignableConcept<_Tp> >();
|
||||
__function_requires< _EqualityComparableConcept<_Tp> >();
|
||||
// typedef typename std::iterator_traits<_Tp>::value_type _V;
|
||||
(void)*__i; // require dereference operator
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_TrivialIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _TrivialIteratorConcept<_Tp> >();
|
||||
*__i = *__j; // require dereference and assignment
|
||||
}
|
||||
_Tp __i, __j;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _InputIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _TrivialIteratorConcept<_Tp> >();
|
||||
// require iterator_traits typedef's
|
||||
typedef typename std::iterator_traits<_Tp>::difference_type _Diff;
|
||||
// __function_requires< _SignedIntegerConcept<_Diff> >();
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
typedef typename std::iterator_traits<_Tp>::pointer _Pt;
|
||||
typedef typename std::iterator_traits<_Tp>::iterator_category _Cat;
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::input_iterator_tag> >();
|
||||
++__i; // require preincrement operator
|
||||
__i++; // require postincrement operator
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp, class _ValueT>
|
||||
struct _OutputIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _AssignableConcept<_Tp> >();
|
||||
++__i; // require preincrement operator
|
||||
__i++; // require postincrement operator
|
||||
*__i++ = __t; // require postincrement and assignment
|
||||
}
|
||||
_Tp __i;
|
||||
_ValueT __t;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _ForwardIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _InputIteratorConcept<_Tp> >();
|
||||
__function_requires< _DefaultConstructibleConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::forward_iterator_tag> >();
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
_Ref __r _IsUnused = *__i;
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_ForwardIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardIteratorConcept<_Tp> >();
|
||||
*__i++ = *__i; // require postincrement and assignment
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _BidirectionalIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardIteratorConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::bidirectional_iterator_tag> >();
|
||||
--__i; // require predecrement operator
|
||||
__i--; // require postdecrement operator
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_BidirectionalIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _BidirectionalIteratorConcept<_Tp> >();
|
||||
__function_requires< _Mutable_ForwardIteratorConcept<_Tp> >();
|
||||
*__i-- = *__i; // require postdecrement and assignment
|
||||
}
|
||||
_Tp __i;
|
||||
};
|
||||
|
||||
|
||||
template <class _Tp>
|
||||
struct _RandomAccessIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _BidirectionalIteratorConcept<_Tp> >();
|
||||
__function_requires< _ComparableConcept<_Tp> >();
|
||||
__function_requires< _ConvertibleConcept<
|
||||
typename std::iterator_traits<_Tp>::iterator_category,
|
||||
std::random_access_iterator_tag> >();
|
||||
// ??? We don't use _Ref, are we just checking for "referenceability"?
|
||||
typedef typename std::iterator_traits<_Tp>::reference _Ref;
|
||||
|
||||
__i += __n; // require assignment addition operator
|
||||
__i = __i + __n; __i = __n + __i; // require addition with difference type
|
||||
__i -= __n; // require assignment subtraction op
|
||||
__i = __i - __n; // require subtraction with
|
||||
// difference type
|
||||
__n = __i - __j; // require difference operator
|
||||
(void)__i[__n]; // require element access operator
|
||||
}
|
||||
_Tp __a, __b;
|
||||
_Tp __i, __j;
|
||||
typename std::iterator_traits<_Tp>::difference_type __n;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct _Mutable_RandomAccessIteratorConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _RandomAccessIteratorConcept<_Tp> >();
|
||||
__function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >();
|
||||
__i[__n] = *__i; // require element access and assignment
|
||||
}
|
||||
_Tp __i;
|
||||
typename std::iterator_traits<_Tp>::difference_type __n;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Container Concepts
|
||||
|
||||
template <class _Container>
|
||||
struct _ContainerConcept
|
||||
{
|
||||
typedef typename _Container::value_type _Value_type;
|
||||
typedef typename _Container::difference_type _Difference_type;
|
||||
typedef typename _Container::size_type _Size_type;
|
||||
typedef typename _Container::const_reference _Const_reference;
|
||||
typedef typename _Container::const_pointer _Const_pointer;
|
||||
typedef typename _Container::const_iterator _Const_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _InputIteratorConcept<_Const_iterator> >();
|
||||
__function_requires< _AssignableConcept<_Container> >();
|
||||
const _Container __c;
|
||||
__i = __c.begin();
|
||||
__i = __c.end();
|
||||
__n = __c.size();
|
||||
__n = __c.max_size();
|
||||
__b = __c.empty();
|
||||
}
|
||||
bool __b;
|
||||
_Const_iterator __i;
|
||||
_Size_type __n;
|
||||
};
|
||||
|
||||
template <class _Container>
|
||||
struct _Mutable_ContainerConcept
|
||||
{
|
||||
typedef typename _Container::value_type _Value_type;
|
||||
typedef typename _Container::reference _Reference;
|
||||
typedef typename _Container::iterator _Iterator;
|
||||
typedef typename _Container::pointer _Pointer;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _ContainerConcept<_Container> >();
|
||||
__function_requires< _AssignableConcept<_Value_type> >();
|
||||
__function_requires< _InputIteratorConcept<_Iterator> >();
|
||||
|
||||
__i = __c.begin();
|
||||
__i = __c.end();
|
||||
__c.swap(__c2);
|
||||
}
|
||||
_Iterator __i;
|
||||
_Container __c, __c2;
|
||||
};
|
||||
|
||||
template <class _ForwardContainer>
|
||||
struct _ForwardContainerConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ContainerConcept<_ForwardContainer> >();
|
||||
typedef typename _ForwardContainer::const_iterator _Const_iterator;
|
||||
__function_requires< _ForwardIteratorConcept<_Const_iterator> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ForwardContainer>
|
||||
struct _Mutable_ForwardContainerConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardContainerConcept<_ForwardContainer> >();
|
||||
__function_requires< _Mutable_ContainerConcept<_ForwardContainer> >();
|
||||
typedef typename _ForwardContainer::iterator _Iterator;
|
||||
__function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ReversibleContainer>
|
||||
struct _ReversibleContainerConcept
|
||||
{
|
||||
typedef typename _ReversibleContainer::const_iterator _Const_iterator;
|
||||
typedef typename _ReversibleContainer::const_reverse_iterator
|
||||
_Const_reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _ForwardContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires< _BidirectionalIteratorConcept<_Const_iterator> >();
|
||||
__function_requires<
|
||||
_BidirectionalIteratorConcept<_Const_reverse_iterator> >();
|
||||
|
||||
const _ReversibleContainer __c;
|
||||
_Const_reverse_iterator __i = __c.rbegin();
|
||||
__i = __c.rend();
|
||||
}
|
||||
};
|
||||
|
||||
template <class _ReversibleContainer>
|
||||
struct _Mutable_ReversibleContainerConcept
|
||||
{
|
||||
typedef typename _ReversibleContainer::iterator _Iterator;
|
||||
typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<_ReversibleContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires<
|
||||
_Mutable_ForwardContainerConcept<_ReversibleContainer> >();
|
||||
__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >();
|
||||
__function_requires<
|
||||
_Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >();
|
||||
|
||||
_Reverse_iterator __i = __c.rbegin();
|
||||
__i = __c.rend();
|
||||
}
|
||||
_ReversibleContainer __c;
|
||||
};
|
||||
|
||||
template <class _RandomAccessContainer>
|
||||
struct _RandomAccessContainerConcept
|
||||
{
|
||||
typedef typename _RandomAccessContainer::size_type _Size_type;
|
||||
typedef typename _RandomAccessContainer::const_reference _Const_reference;
|
||||
typedef typename _RandomAccessContainer::const_iterator _Const_iterator;
|
||||
typedef typename _RandomAccessContainer::const_reverse_iterator
|
||||
_Const_reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<
|
||||
_ReversibleContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires< _RandomAccessIteratorConcept<_Const_iterator> >();
|
||||
__function_requires<
|
||||
_RandomAccessIteratorConcept<_Const_reverse_iterator> >();
|
||||
|
||||
const _RandomAccessContainer __c;
|
||||
_Const_reference __r _IsUnused = __c[__n];
|
||||
}
|
||||
_Size_type __n;
|
||||
};
|
||||
|
||||
template <class _RandomAccessContainer>
|
||||
struct _Mutable_RandomAccessContainerConcept
|
||||
{
|
||||
typedef typename _RandomAccessContainer::size_type _Size_type;
|
||||
typedef typename _RandomAccessContainer::reference _Reference;
|
||||
typedef typename _RandomAccessContainer::iterator _Iterator;
|
||||
typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires<
|
||||
_RandomAccessContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires<
|
||||
_Mutable_ReversibleContainerConcept<_RandomAccessContainer> >();
|
||||
__function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >();
|
||||
__function_requires<
|
||||
_Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >();
|
||||
|
||||
_Reference __r _IsUnused = __c[__i];
|
||||
}
|
||||
_Size_type __i;
|
||||
_RandomAccessContainer __c;
|
||||
};
|
||||
|
||||
// A Sequence is inherently mutable
|
||||
template <class _Sequence>
|
||||
struct _SequenceConcept
|
||||
{
|
||||
typedef typename _Sequence::reference _Reference;
|
||||
typedef typename _Sequence::const_reference _Const_reference;
|
||||
|
||||
void __constraints() {
|
||||
// Matt Austern's book puts DefaultConstructible here, the C++
|
||||
// standard places it in Container
|
||||
// function_requires< DefaultConstructible<Sequence> >();
|
||||
__function_requires< _Mutable_ForwardContainerConcept<_Sequence> >();
|
||||
__function_requires< _DefaultConstructibleConcept<_Sequence> >();
|
||||
|
||||
_Sequence
|
||||
__c _IsUnused(__n, __t),
|
||||
__c2 _IsUnused(__first, __last);
|
||||
|
||||
__c.insert(__p, __t);
|
||||
__c.insert(__p, __n, __t);
|
||||
__c.insert(__p, __first, __last);
|
||||
|
||||
__c.erase(__p);
|
||||
__c.erase(__p, __q);
|
||||
|
||||
_Reference __r _IsUnused = __c.front();
|
||||
|
||||
__const_constraints(__c);
|
||||
}
|
||||
void __const_constraints(const _Sequence& __c) {
|
||||
_Const_reference __r _IsUnused = __c.front();
|
||||
}
|
||||
typename _Sequence::value_type __t;
|
||||
typename _Sequence::size_type __n;
|
||||
typename _Sequence::value_type *__first, *__last;
|
||||
typename _Sequence::iterator __p, __q;
|
||||
};
|
||||
|
||||
template <class _FrontInsertionSequence>
|
||||
struct _FrontInsertionSequenceConcept
|
||||
{
|
||||
void __constraints() {
|
||||
__function_requires< _SequenceConcept<_FrontInsertionSequence> >();
|
||||
|
||||
__c.push_front(__t);
|
||||
__c.pop_front();
|
||||
}
|
||||
_FrontInsertionSequence __c;
|
||||
typename _FrontInsertionSequence::value_type __t;
|
||||
};
|
||||
|
||||
template <class _BackInsertionSequence>
|
||||
struct _BackInsertionSequenceConcept
|
||||
{
|
||||
typedef typename _BackInsertionSequence::reference _Reference;
|
||||
typedef typename _BackInsertionSequence::const_reference _Const_reference;
|
||||
|
||||
void __constraints() {
|
||||
__function_requires< _SequenceConcept<_BackInsertionSequence> >();
|
||||
|
||||
__c.push_back(__t);
|
||||
__c.pop_back();
|
||||
_Reference __r _IsUnused = __c.back();
|
||||
}
|
||||
void __const_constraints(const _BackInsertionSequence& __c) {
|
||||
_Const_reference __r _IsUnused = __c.back();
|
||||
};
|
||||
_BackInsertionSequence __c;
|
||||
typename _BackInsertionSequence::value_type __t;
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#undef _IsUnused
|
||||
|
||||
#endif // _GLIBCXX_BOOST_CONCEPT_CHECK
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++0x_warning.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iosfwd}
|
||||
*/
|
||||
|
||||
#ifndef _CXX0X_WARNING_H
|
||||
#define _CXX0X_WARNING_H 1
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
#error This file requires compiler and library support \
|
||||
for the ISO C++ 2011 standard. This support must be enabled \
|
||||
with the -std=c++11 or -std=gnu++11 compiler options.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Base to std::allocator -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/c++allocator.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_CXX_ALLOCATOR_H
|
||||
#define _GLIBCXX_CXX_ALLOCATOR_H 1
|
||||
|
||||
#include "../ext/new_allocator.h"
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* @brief An alias to the base class for std::allocator.
|
||||
* @ingroup allocators
|
||||
*
|
||||
* Used to set the std::allocator base class to
|
||||
* __gnu_cxx::new_allocator.
|
||||
*
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
|
||||
}
|
||||
#else
|
||||
// Define new_allocator as the base class to std::allocator.
|
||||
# define __allocator_base __gnu_cxx::new_allocator
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,81 @@
|
|||
// Concept-checking control -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/concept_check.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
#ifndef _CONCEPT_CHECK_H
|
||||
#define _CONCEPT_CHECK_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
// All places in libstdc++-v3 where these are used, or /might/ be used, or
|
||||
// don't need to be used, or perhaps /should/ be used, are commented with
|
||||
// "concept requirements" (and maybe some more text). So grep like crazy
|
||||
// if you're looking for additional places to use these.
|
||||
|
||||
// Concept-checking code is off by default unless users turn it on via
|
||||
// configure options or editing c++config.h.
|
||||
// It is not supported for freestanding implementations.
|
||||
|
||||
#if !defined(_GLIBCXX_CONCEPT_CHECKS) || !_GLIBCXX_HOSTED
|
||||
|
||||
#define __glibcxx_function_requires(...)
|
||||
#define __glibcxx_class_requires(_a,_b)
|
||||
#define __glibcxx_class_requires2(_a,_b,_c)
|
||||
#define __glibcxx_class_requires3(_a,_b,_c,_d)
|
||||
#define __glibcxx_class_requires4(_a,_b,_c,_d,_e)
|
||||
|
||||
#else // the checks are on
|
||||
|
||||
#include "../bits/boost_concept_check.h"
|
||||
|
||||
// Note that the obvious and elegant approach of
|
||||
//
|
||||
//#define glibcxx_function_requires(C) debug::function_requires< debug::C >()
|
||||
//
|
||||
// won't work due to concept templates with more than one parameter, e.g.,
|
||||
// BinaryPredicateConcept. The preprocessor tries to split things up on
|
||||
// the commas in the template argument list. We can't use an inner pair of
|
||||
// parenthesis to hide the commas, because "debug::(Temp<Foo,Bar>)" isn't
|
||||
// a valid instantiation pattern. Thus, we steal a feature from C99.
|
||||
|
||||
#define __glibcxx_function_requires(...) \
|
||||
__gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >();
|
||||
#define __glibcxx_class_requires(_a,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires2(_a,_b,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires3(_a,_b,_c,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C);
|
||||
#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \
|
||||
_GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C);
|
||||
|
||||
#endif // enable/disable
|
||||
|
||||
#endif // _GLIBCXX_CONCEPT_CHECK
|
||||
|
|
@ -0,0 +1,415 @@
|
|||
// The -*- C++ -*- type traits classes for internal use in libstdc++
|
||||
|
||||
// Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/cpp_type_traits.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{ext/type_traits}
|
||||
*/
|
||||
|
||||
// Written by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
|
||||
|
||||
#ifndef _CPP_TYPE_TRAITS_H
|
||||
#define _CPP_TYPE_TRAITS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
//
|
||||
// This file provides some compile-time information about various types.
|
||||
// These representations were designed, on purpose, to be constant-expressions
|
||||
// and not types as found in <bits/type_traits.h>. In particular, they
|
||||
// can be used in control structures and the optimizer hopefully will do
|
||||
// the obvious thing.
|
||||
//
|
||||
// Why integral expressions, and not functions nor types?
|
||||
// Firstly, these compile-time entities are used as template-arguments
|
||||
// so function return values won't work: We need compile-time entities.
|
||||
// We're left with types and constant integral expressions.
|
||||
// Secondly, from the point of view of ease of use, type-based compile-time
|
||||
// information is -not- *that* convenient. On has to write lots of
|
||||
// overloaded functions and to hope that the compiler will select the right
|
||||
// one. As a net effect, the overall structure isn't very clear at first
|
||||
// glance.
|
||||
// Thirdly, partial ordering and overload resolution (of function templates)
|
||||
// is highly costly in terms of compiler-resource. It is a Good Thing to
|
||||
// keep these resource consumption as least as possible.
|
||||
//
|
||||
// See valarray_array.h for a case use.
|
||||
//
|
||||
// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06.
|
||||
//
|
||||
// Update 2005: types are also provided and <bits/type_traits.h> has been
|
||||
// removed.
|
||||
//
|
||||
|
||||
extern "C++" {
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct __true_type { };
|
||||
struct __false_type { };
|
||||
|
||||
template<bool>
|
||||
struct __truth_type
|
||||
{ typedef __false_type __type; };
|
||||
|
||||
template<>
|
||||
struct __truth_type<true>
|
||||
{ typedef __true_type __type; };
|
||||
|
||||
// N.B. The conversions to bool are needed due to the issue
|
||||
// explained in c++/19404.
|
||||
template<class _Sp, class _Tp>
|
||||
struct __traitor
|
||||
{
|
||||
enum { __value = bool(_Sp::__value) || bool(_Tp::__value) };
|
||||
typedef typename __truth_type<__value>::__type __type;
|
||||
};
|
||||
|
||||
// Compare for equality of types.
|
||||
template<typename, typename>
|
||||
struct __are_same
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __are_same<_Tp, _Tp>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
// Holds if the template-argument is a void type.
|
||||
template<typename _Tp>
|
||||
struct __is_void
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_void<void>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
//
|
||||
// Integer types
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_integer
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
// Thirteen specializations (yes there are eleven standard integer
|
||||
// types; <em>long long</em> and <em>unsigned long long</em> are
|
||||
// supported as extensions). Up to four target-specific __int<N>
|
||||
// types are supported as well.
|
||||
template<>
|
||||
struct __is_integer<bool>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<signed char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<unsigned char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
# ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template<>
|
||||
struct __is_integer<wchar_t>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
# endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<>
|
||||
struct __is_integer<char16_t>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<char32_t>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct __is_integer<short>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<unsigned short>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<int>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<unsigned int>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<long>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<unsigned long>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<long long>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_integer<unsigned long long>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
#define __INT_N(TYPE) \
|
||||
template<> \
|
||||
struct __is_integer<TYPE> \
|
||||
{ \
|
||||
enum { __value = 1 }; \
|
||||
typedef __true_type __type; \
|
||||
}; \
|
||||
template<> \
|
||||
struct __is_integer<unsigned TYPE> \
|
||||
{ \
|
||||
enum { __value = 1 }; \
|
||||
typedef __true_type __type; \
|
||||
};
|
||||
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_0
|
||||
__INT_N(__GLIBCXX_TYPE_INT_N_0)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_1
|
||||
__INT_N(__GLIBCXX_TYPE_INT_N_1)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_2
|
||||
__INT_N(__GLIBCXX_TYPE_INT_N_2)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_3
|
||||
__INT_N(__GLIBCXX_TYPE_INT_N_3)
|
||||
#endif
|
||||
|
||||
#undef __INT_N
|
||||
|
||||
//
|
||||
// Floating point types
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_floating
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
// three specializations (float, double and 'long double')
|
||||
template<>
|
||||
struct __is_floating<float>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_floating<double>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_floating<long double>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
//
|
||||
// Pointer types
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_pointer
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_pointer<_Tp*>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
//
|
||||
// An arithmetic type is an integer type or a floating point type
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_arithmetic
|
||||
: public __traitor<__is_integer<_Tp>, __is_floating<_Tp> >
|
||||
{ };
|
||||
|
||||
//
|
||||
// A scalar type is an arithmetic type or a pointer type
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_scalar
|
||||
: public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> >
|
||||
{ };
|
||||
|
||||
//
|
||||
// For use in std::copy and std::find overloads for streambuf iterators.
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_char
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_char<char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template<>
|
||||
struct __is_char<wchar_t>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_byte
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_byte<char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_byte<signed char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __is_byte<unsigned char>
|
||||
{
|
||||
enum { __value = 1 };
|
||||
typedef __true_type __type;
|
||||
};
|
||||
|
||||
//
|
||||
// Move iterator type
|
||||
//
|
||||
template<typename _Tp>
|
||||
struct __is_move_iterator
|
||||
{
|
||||
enum { __value = 0 };
|
||||
typedef __false_type __type;
|
||||
};
|
||||
|
||||
// Fallback implementation of the function in bits/stl_iterator.h used to
|
||||
// remove the move_iterator wrapper.
|
||||
template<typename _Iterator>
|
||||
inline _Iterator
|
||||
__miter_base(_Iterator __it)
|
||||
{ return __it; }
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
} // extern "C++"
|
||||
|
||||
#endif //_CPP_TYPE_TRAITS_H
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Specific definitions for generic platforms -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2005-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/cpu_defines.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iosfwd}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_CPU_DEFINES
|
||||
#define _GLIBCXX_CPU_DEFINES 1
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
// <bits/enable_special_members.h> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2013-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/enable_special_members.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly.
|
||||
*/
|
||||
|
||||
#ifndef _ENABLE_SPECIAL_MEMBERS_H
|
||||
#define _ENABLE_SPECIAL_MEMBERS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct _Enable_default_constructor_tag
|
||||
{
|
||||
explicit constexpr _Enable_default_constructor_tag() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A mixin helper to conditionally enable or disable the default
|
||||
* constructor.
|
||||
* @sa _Enable_special_members
|
||||
*/
|
||||
template<bool _Switch, typename _Tag = void>
|
||||
struct _Enable_default_constructor
|
||||
{
|
||||
constexpr _Enable_default_constructor() noexcept = default;
|
||||
constexpr _Enable_default_constructor(_Enable_default_constructor const&)
|
||||
noexcept = default;
|
||||
constexpr _Enable_default_constructor(_Enable_default_constructor&&)
|
||||
noexcept = default;
|
||||
_Enable_default_constructor&
|
||||
operator=(_Enable_default_constructor const&) noexcept = default;
|
||||
_Enable_default_constructor&
|
||||
operator=(_Enable_default_constructor&&) noexcept = default;
|
||||
|
||||
// Can be used in other ctors.
|
||||
constexpr explicit
|
||||
_Enable_default_constructor(_Enable_default_constructor_tag) { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A mixin helper to conditionally enable or disable the default
|
||||
* destructor.
|
||||
* @sa _Enable_special_members
|
||||
*/
|
||||
template<bool _Switch, typename _Tag = void>
|
||||
struct _Enable_destructor { };
|
||||
|
||||
/**
|
||||
* @brief A mixin helper to conditionally enable or disable the copy/move
|
||||
* special members.
|
||||
* @sa _Enable_special_members
|
||||
*/
|
||||
template<bool _Copy, bool _CopyAssignment,
|
||||
bool _Move, bool _MoveAssignment,
|
||||
typename _Tag = void>
|
||||
struct _Enable_copy_move { };
|
||||
|
||||
/**
|
||||
* @brief A mixin helper to conditionally enable or disable the special
|
||||
* members.
|
||||
*
|
||||
* The @c _Tag type parameter is to make mixin bases unique and thus avoid
|
||||
* ambiguities.
|
||||
*/
|
||||
template<bool _Default, bool _Destructor,
|
||||
bool _Copy, bool _CopyAssignment,
|
||||
bool _Move, bool _MoveAssignment,
|
||||
typename _Tag = void>
|
||||
struct _Enable_special_members
|
||||
: private _Enable_default_constructor<_Default, _Tag>,
|
||||
private _Enable_destructor<_Destructor, _Tag>,
|
||||
private _Enable_copy_move<_Copy, _CopyAssignment,
|
||||
_Move, _MoveAssignment,
|
||||
_Tag>
|
||||
{ };
|
||||
|
||||
// Boilerplate follows.
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_default_constructor<false, _Tag>
|
||||
{
|
||||
constexpr _Enable_default_constructor() noexcept = delete;
|
||||
constexpr _Enable_default_constructor(_Enable_default_constructor const&)
|
||||
noexcept = default;
|
||||
constexpr _Enable_default_constructor(_Enable_default_constructor&&)
|
||||
noexcept = default;
|
||||
_Enable_default_constructor&
|
||||
operator=(_Enable_default_constructor const&) noexcept = default;
|
||||
_Enable_default_constructor&
|
||||
operator=(_Enable_default_constructor&&) noexcept = default;
|
||||
|
||||
// Can be used in other ctors.
|
||||
constexpr explicit
|
||||
_Enable_default_constructor(_Enable_default_constructor_tag) { }
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_destructor<false, _Tag>
|
||||
{ ~_Enable_destructor() noexcept = delete; };
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, true, true, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, false, true, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, false, true, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, true, false, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, true, false, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, false, false, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, false, false, true, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = default;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, true, true, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, true, true, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, false, true, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, false, true, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, true, false, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, true, false, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = default;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<true, false, false, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template<typename _Tag>
|
||||
struct _Enable_copy_move<false, false, false, false, _Tag>
|
||||
{
|
||||
constexpr _Enable_copy_move() noexcept = default;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete;
|
||||
constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move const&) noexcept = delete;
|
||||
_Enable_copy_move&
|
||||
operator=(_Enable_copy_move&&) noexcept = delete;
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // _ENABLE_SPECIAL_MEMBERS_H
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// -fno-exceptions Support -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/exception_defines.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{exception}
|
||||
*/
|
||||
|
||||
#ifndef _EXCEPTION_DEFINES_H
|
||||
#define _EXCEPTION_DEFINES_H 1
|
||||
|
||||
#if ! __cpp_exceptions
|
||||
// Iff -fno-exceptions, transform error handling code to work without it.
|
||||
# define __try if (true)
|
||||
# define __catch(X) if (false)
|
||||
# define __throw_exception_again
|
||||
#else
|
||||
// Else proceed normally.
|
||||
# define __try try
|
||||
# define __catch(X) catch(X)
|
||||
# define __throw_exception_again throw
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// Function-Based Exception Support -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/functexcept.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{exception}
|
||||
*
|
||||
* This header provides support for -fno-exceptions.
|
||||
*/
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 19.1 Exception classes
|
||||
//
|
||||
|
||||
#ifndef _FUNCTEXCEPT_H
|
||||
#define _FUNCTEXCEPT_H 1
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../bits/exception_defines.h"
|
||||
|
||||
#ifndef __AVR__
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Helper for exception objects in <except>
|
||||
void
|
||||
__throw_bad_exception(void) __attribute__((__noreturn__));
|
||||
|
||||
// Helper for exception objects in <new>
|
||||
void
|
||||
__throw_bad_alloc(void) __attribute__((__noreturn__));
|
||||
|
||||
// Helper for exception objects in <typeinfo>
|
||||
void
|
||||
__throw_bad_cast(void) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_bad_typeid(void) __attribute__((__noreturn__));
|
||||
|
||||
// Helpers for exception objects in <stdexcept>
|
||||
void
|
||||
__throw_logic_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_domain_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_invalid_argument(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_length_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_out_of_range(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__))
|
||||
__attribute__((__format__(__gnu_printf__, 1, 2)));
|
||||
|
||||
void
|
||||
__throw_runtime_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_range_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_overflow_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_underflow_error(const char*) __attribute__((__noreturn__));
|
||||
|
||||
// Helpers for exception objects in <ios>
|
||||
void
|
||||
__throw_ios_failure(const char*) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_system_error(int) __attribute__((__noreturn__));
|
||||
|
||||
void
|
||||
__throw_future_error(int) __attribute__((__noreturn__));
|
||||
|
||||
// Helpers for exception objects in <functional>
|
||||
void
|
||||
__throw_bad_function_call() __attribute__((__noreturn__));
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#else // __AVR__
|
||||
|
||||
#include <AH/Error/Error.hpp>
|
||||
|
||||
// Helper for exception objects in <except>
|
||||
#define __throw_bad_exception() FATAL_ERROR(F("std::bad_exception"), 0x1111)
|
||||
|
||||
// Helper for exception objects in <new>
|
||||
#define __throw_bad_alloc() FATAL_ERROR(F("std::bad_alloc"), 0x1112)
|
||||
|
||||
// Helper for exception objects in <typeinfo>
|
||||
#define __throw_bad_cast() FATAL_ERROR(F("std::bad_cast"), 0x1113)
|
||||
|
||||
#define __throw_bad_typeid() FATAL_ERROR(F("std::bad_typeid"), 0x1114)
|
||||
|
||||
// Helpers for exception objects in <stdexcept>
|
||||
#define __throw_logic_error(msg) FATAL_ERROR(F("std::logic_error: ") << msg, 0x1115)
|
||||
|
||||
#define __throw_domain_error(msg) FATAL_ERROR(F("std::domain_error: ") << msg, 0x1116)
|
||||
|
||||
#define __throw_invalid_argument(msg) FATAL_ERROR(F("std::invalid_argument: ") << msg, 0x1117)
|
||||
|
||||
#define __throw_length_error(msg) FATAL_ERROR(F("std::length_error: ") << msg, 0x1118)
|
||||
|
||||
#define __throw_out_of_range(msg) FATAL_ERROR(F("std::out_of_range: ") << msg, 0x1119)
|
||||
|
||||
// void
|
||||
// __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__))
|
||||
// __attribute__((__format__(__gnu_printf__, 1, 2)))
|
||||
#define __throw_out_of_range_index_length(msg, index, size) \
|
||||
FATAL_ERROR(F("std::out_of_range: ") << msg << F("; index = ") << index << F(", length = ") << size, 0x1119)
|
||||
|
||||
#define __throw_runtime_error(msg) FATAL_ERROR(F("std::runtime_error: ") << msg, 0x111A)
|
||||
|
||||
#define __throw_range_error(msg) FATAL_ERROR(F("std::range_error: ") << msg, 0x111B)
|
||||
|
||||
#define __throw_overflow_error(msg) FATAL_ERROR(F("std::overflow_error: ") << msg, 0x111C)
|
||||
|
||||
#define __throw_underflow_error(msg) FATAL_ERROR(F("std::underflow_error: ") << msg, 0x111D)
|
||||
|
||||
// Helpers for exception objects in <ios>
|
||||
#define __throw_ios_failure(msg) FATAL_ERROR(F("std::ios_failure: ") << msg, 0x111E)
|
||||
|
||||
#define __throw_system_error(code) FATAL_ERROR(F("std::system_error: ") << code, 0x1120)
|
||||
|
||||
#define __throw_future_error(code) FATAL_ERROR(F("std::future_error: ") << code, 0x1121)
|
||||
|
||||
|
||||
// Helpers for exception objects in <functional>
|
||||
#define __throw_bad_function_call() FATAL_ERROR(F("std::bad_function_call"), 0x111F)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
// functional_hash.h header -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/functional_hash.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{functional}
|
||||
*/
|
||||
|
||||
#ifndef _FUNCTIONAL_HASH_H
|
||||
#define _FUNCTIONAL_HASH_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/hash_bytes.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/** @defgroup hashes Hashes
|
||||
* @ingroup functors
|
||||
*
|
||||
* Hashing functors taking a variable type and returning a @c std::size_t.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _Result, typename _Arg>
|
||||
struct __hash_base
|
||||
{
|
||||
typedef _Result result_type;
|
||||
typedef _Arg argument_type;
|
||||
};
|
||||
|
||||
/// Primary class template hash.
|
||||
template<typename _Tp>
|
||||
struct hash;
|
||||
|
||||
template<typename _Tp, typename = void>
|
||||
struct __poison_hash
|
||||
{
|
||||
static constexpr bool __enable_hash_call = false;
|
||||
private:
|
||||
// Private rather than deleted to be non-trivially-copyable.
|
||||
__poison_hash(__poison_hash&&);
|
||||
~__poison_hash();
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __poison_hash<_Tp, __void_t<decltype(hash<_Tp>()(declval<_Tp>()))>>
|
||||
{
|
||||
static constexpr bool __enable_hash_call = true;
|
||||
};
|
||||
|
||||
// Helper struct for SFINAE-poisoning non-enum types.
|
||||
template<typename _Tp, bool = is_enum<_Tp>::value>
|
||||
struct __hash_enum
|
||||
{
|
||||
private:
|
||||
// Private rather than deleted to be non-trivially-copyable.
|
||||
__hash_enum(__hash_enum&&);
|
||||
~__hash_enum();
|
||||
};
|
||||
|
||||
// Helper struct for hash with enum types.
|
||||
template<typename _Tp>
|
||||
struct __hash_enum<_Tp, true> : public __hash_base<size_t, _Tp>
|
||||
{
|
||||
size_t
|
||||
operator()(_Tp __val) const noexcept
|
||||
{
|
||||
using __type = typename underlying_type<_Tp>::type;
|
||||
return hash<__type>{}(static_cast<__type>(__val));
|
||||
}
|
||||
};
|
||||
|
||||
/// Primary class template hash, usable for enum types only.
|
||||
// Use with non-enum types still SFINAES.
|
||||
template<typename _Tp>
|
||||
struct hash : __hash_enum<_Tp>
|
||||
{ };
|
||||
|
||||
/// Partial specializations for pointer types.
|
||||
template<typename _Tp>
|
||||
struct hash<_Tp*> : public __hash_base<size_t, _Tp*>
|
||||
{
|
||||
size_t
|
||||
operator()(_Tp* __p) const noexcept
|
||||
{ return reinterpret_cast<size_t>(__p); }
|
||||
};
|
||||
|
||||
// Explicit specializations for integer types.
|
||||
#define _Cxx_hashtable_define_trivial_hash(_Tp) \
|
||||
template<> \
|
||||
struct hash<_Tp> : public __hash_base<size_t, _Tp> \
|
||||
{ \
|
||||
size_t \
|
||||
operator()(_Tp __val) const noexcept \
|
||||
{ return static_cast<size_t>(__val); } \
|
||||
};
|
||||
|
||||
/// Explicit specialization for bool.
|
||||
_Cxx_hashtable_define_trivial_hash(bool)
|
||||
|
||||
/// Explicit specialization for char.
|
||||
_Cxx_hashtable_define_trivial_hash(char)
|
||||
|
||||
/// Explicit specialization for signed char.
|
||||
_Cxx_hashtable_define_trivial_hash(signed char)
|
||||
|
||||
/// Explicit specialization for unsigned char.
|
||||
_Cxx_hashtable_define_trivial_hash(unsigned char)
|
||||
|
||||
/// Explicit specialization for wchar_t.
|
||||
_Cxx_hashtable_define_trivial_hash(wchar_t)
|
||||
|
||||
/// Explicit specialization for char16_t.
|
||||
_Cxx_hashtable_define_trivial_hash(char16_t)
|
||||
|
||||
/// Explicit specialization for char32_t.
|
||||
_Cxx_hashtable_define_trivial_hash(char32_t)
|
||||
|
||||
/// Explicit specialization for short.
|
||||
_Cxx_hashtable_define_trivial_hash(short)
|
||||
|
||||
/// Explicit specialization for int.
|
||||
_Cxx_hashtable_define_trivial_hash(int)
|
||||
|
||||
/// Explicit specialization for long.
|
||||
_Cxx_hashtable_define_trivial_hash(long)
|
||||
|
||||
/// Explicit specialization for long long.
|
||||
_Cxx_hashtable_define_trivial_hash(long long)
|
||||
|
||||
/// Explicit specialization for unsigned short.
|
||||
_Cxx_hashtable_define_trivial_hash(unsigned short)
|
||||
|
||||
/// Explicit specialization for unsigned int.
|
||||
_Cxx_hashtable_define_trivial_hash(unsigned int)
|
||||
|
||||
/// Explicit specialization for unsigned long.
|
||||
_Cxx_hashtable_define_trivial_hash(unsigned long)
|
||||
|
||||
/// Explicit specialization for unsigned long long.
|
||||
_Cxx_hashtable_define_trivial_hash(unsigned long long)
|
||||
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_0
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0)
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_1
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1)
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_2
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2)
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned)
|
||||
#endif
|
||||
#ifdef __GLIBCXX_TYPE_INT_N_3
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3)
|
||||
_Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned)
|
||||
#endif
|
||||
|
||||
#undef _Cxx_hashtable_define_trivial_hash
|
||||
|
||||
struct _Hash_impl
|
||||
{
|
||||
static size_t
|
||||
hash(const void* __ptr, size_t __clength,
|
||||
size_t __seed = static_cast<size_t>(0xc70f6907UL))
|
||||
{ return _Hash_bytes(__ptr, __clength, __seed); }
|
||||
|
||||
template<typename _Tp>
|
||||
static size_t
|
||||
hash(const _Tp& __val)
|
||||
{ return hash(&__val, sizeof(__val)); }
|
||||
|
||||
template<typename _Tp>
|
||||
static size_t
|
||||
__hash_combine(const _Tp& __val, size_t __hash)
|
||||
{ return hash(&__val, sizeof(__val), __hash); }
|
||||
};
|
||||
|
||||
// A hash function similar to FNV-1a (see PR59406 for how it differs).
|
||||
struct _Fnv_hash_impl
|
||||
{
|
||||
static size_t
|
||||
hash(const void* __ptr, size_t __clength,
|
||||
size_t __seed = static_cast<size_t>(2166136261UL))
|
||||
{ return _Fnv_hash_bytes(__ptr, __clength, __seed); }
|
||||
|
||||
template<typename _Tp>
|
||||
static size_t
|
||||
hash(const _Tp& __val)
|
||||
{ return hash(&__val, sizeof(__val)); }
|
||||
|
||||
template<typename _Tp>
|
||||
static size_t
|
||||
__hash_combine(const _Tp& __val, size_t __hash)
|
||||
{ return hash(&__val, sizeof(__val), __hash); }
|
||||
};
|
||||
|
||||
/// Specialization for float.
|
||||
template<>
|
||||
struct hash<float> : public __hash_base<size_t, float>
|
||||
{
|
||||
size_t
|
||||
operator()(float __val) const noexcept
|
||||
{
|
||||
// 0 and -0 both hash to zero.
|
||||
return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Specialization for double.
|
||||
template<>
|
||||
struct hash<double> : public __hash_base<size_t, double>
|
||||
{
|
||||
size_t
|
||||
operator()(double __val) const noexcept
|
||||
{
|
||||
// 0 and -0 both hash to zero.
|
||||
return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Specialization for long double.
|
||||
template<>
|
||||
struct hash<long double>
|
||||
: public __hash_base<size_t, long double>
|
||||
{
|
||||
_GLIBCXX_PURE size_t
|
||||
operator()(long double __val) const noexcept;
|
||||
};
|
||||
|
||||
// @} group hashes
|
||||
|
||||
// Hint about performance of hash functor. If not fast the hash-based
|
||||
// containers will cache the hash code.
|
||||
// Default behavior is to consider that hashers are fast unless specified
|
||||
// otherwise.
|
||||
template<typename _Hash>
|
||||
struct __is_fast_hash : public std::true_type
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct __is_fast_hash<hash<long double>> : public std::false_type
|
||||
{ };
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif // _FUNCTIONAL_HASH_H
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Declarations for hash functions. -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2010-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/hash_bytes.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{functional}
|
||||
*/
|
||||
|
||||
#ifndef _HASH_BYTES_H
|
||||
#define _HASH_BYTES_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
namespace std
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Hash function implementation for the nontrivial specialization.
|
||||
// All of them are based on a primitive that hashes a pointer to a
|
||||
// byte array. The actual hash algorithm is not guaranteed to stay
|
||||
// the same from release to release -- it may be updated or tuned to
|
||||
// improve hash quality or speed.
|
||||
size_t
|
||||
_Hash_bytes(const void* __ptr, size_t __len, size_t __seed);
|
||||
|
||||
// A similar hash primitive, using the FNV hash algorithm. This
|
||||
// algorithm is guaranteed to stay the same from release to release.
|
||||
// (although it might not produce the same values on different
|
||||
// machines.)
|
||||
size_t
|
||||
_Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed);
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Implementation of INVOKE -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/bits/invoke.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{functional}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_INVOKE_H
|
||||
#define _GLIBCXX_INVOKE_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include "../bits/c++0x_warning.h"
|
||||
#else
|
||||
|
||||
#include "../type_traits"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Used by __invoke_impl instead of std::forward<_Tp> so that a
|
||||
// reference_wrapper is converted to an lvalue-reference.
|
||||
template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type>
|
||||
constexpr _Up&&
|
||||
__invfwd(typename remove_reference<_Tp>::type& __t) noexcept
|
||||
{ return static_cast<_Up&&>(__t); }
|
||||
|
||||
template<typename _Res, typename _Fn, typename... _Args>
|
||||
constexpr _Res
|
||||
__invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
|
||||
{ return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
constexpr _Res
|
||||
__invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
|
||||
_Args&&... __args)
|
||||
{ return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
|
||||
constexpr _Res
|
||||
__invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
|
||||
_Args&&... __args)
|
||||
{
|
||||
return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template<typename _Res, typename _MemPtr, typename _Tp>
|
||||
constexpr _Res
|
||||
__invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t)
|
||||
{ return __invfwd<_Tp>(__t).*__f; }
|
||||
|
||||
template<typename _Res, typename _MemPtr, typename _Tp>
|
||||
constexpr _Res
|
||||
__invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t)
|
||||
{ return (*std::forward<_Tp>(__t)).*__f; }
|
||||
|
||||
/// Invoke a callable object.
|
||||
template<typename _Callable, typename... _Args>
|
||||
constexpr typename __invoke_result<_Callable, _Args...>::type
|
||||
__invoke(_Callable&& __fn, _Args&&... __args)
|
||||
noexcept(__is_nothrow_invocable<_Callable, _Args...>::value)
|
||||
{
|
||||
using __result = __invoke_result<_Callable, _Args...>;
|
||||
using __type = typename __result::type;
|
||||
using __tag = typename __result::__invoke_type;
|
||||
return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _GLIBCXX_INVOKE_H
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// <memory> Forward declarations -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996-1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/memoryfwd.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _MEMORYFWD_H
|
||||
#define _MEMORYFWD_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @defgroup allocators Allocators
|
||||
* @ingroup memory
|
||||
*
|
||||
* Classes encapsulating memory operations.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename>
|
||||
class allocator;
|
||||
|
||||
template<>
|
||||
class allocator<void>;
|
||||
|
||||
/// Declare uses_allocator so it can be specialized in \<queue\> etc.
|
||||
template<typename, typename>
|
||||
struct uses_allocator;
|
||||
|
||||
/// @} group memory
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
// Move, forward and identity for C++11 + swap -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/move.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{utility}
|
||||
*/
|
||||
|
||||
#ifndef _MOVE_H
|
||||
#define _MOVE_H 1
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../bits/concept_check.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Used, in C++03 mode too, by allocators, etc.
|
||||
/**
|
||||
* @brief Same as C++11 std::addressof
|
||||
* @ingroup utilities
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX_CONSTEXPR _Tp*
|
||||
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
|
||||
{ return __builtin_addressof(__r); }
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../type_traits" // Brings in std::declval too.
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Forward an lvalue.
|
||||
* @return The parameter cast to the specified type.
|
||||
*
|
||||
* This function is used to implement "perfect forwarding".
|
||||
*/
|
||||
template<typename _Tp>
|
||||
constexpr _Tp&&
|
||||
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
|
||||
{ return static_cast<_Tp&&>(__t); }
|
||||
|
||||
/**
|
||||
* @brief Forward an rvalue.
|
||||
* @return The parameter cast to the specified type.
|
||||
*
|
||||
* This function is used to implement "perfect forwarding".
|
||||
*/
|
||||
template<typename _Tp>
|
||||
constexpr _Tp&&
|
||||
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
|
||||
{
|
||||
static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
|
||||
" substituting _Tp is an lvalue reference type");
|
||||
return static_cast<_Tp&&>(__t);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a value to an rvalue.
|
||||
* @param __t A thing of arbitrary type.
|
||||
* @return The parameter cast to an rvalue-reference to allow moving it.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
constexpr typename std::remove_reference<_Tp>::type&&
|
||||
move(_Tp&& __t) noexcept
|
||||
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
|
||||
|
||||
|
||||
template<typename _Tp>
|
||||
struct __move_if_noexcept_cond
|
||||
: public __and_<__not_<is_nothrow_move_constructible<_Tp>>,
|
||||
is_copy_constructible<_Tp>>::type { };
|
||||
|
||||
/**
|
||||
* @brief Conditionally convert a value to an rvalue.
|
||||
* @param __x A thing of arbitrary type.
|
||||
* @return The parameter, possibly cast to an rvalue-reference.
|
||||
*
|
||||
* Same as std::move unless the type's move constructor could throw and the
|
||||
* type is copyable, in which case an lvalue-reference is returned instead.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
constexpr typename
|
||||
conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
|
||||
move_if_noexcept(_Tp& __x) noexcept
|
||||
{ return std::move(__x); }
|
||||
|
||||
// declval, from type_traits.
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2296. std::addressof should be constexpr
|
||||
# define __cpp_lib_addressof_constexpr 201603
|
||||
#endif
|
||||
/**
|
||||
* @brief Returns the actual address of the object or function
|
||||
* referenced by r, even in the presence of an overloaded
|
||||
* operator&.
|
||||
* @param __r Reference to an object or function.
|
||||
* @return The actual address.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX17_CONSTEXPR _Tp*
|
||||
addressof(_Tp& __r) noexcept
|
||||
{ return std::__addressof(__r); }
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2598. addressof works on temporaries
|
||||
template<typename _Tp>
|
||||
const _Tp* addressof(const _Tp&&) = delete;
|
||||
|
||||
// C++11 version of std::exchange for internal use.
|
||||
template <typename _Tp, typename _Up = _Tp>
|
||||
inline _Tp
|
||||
__exchange(_Tp& __obj, _Up&& __new_val)
|
||||
{
|
||||
_Tp __old_val = std::move(__obj);
|
||||
__obj = std::forward<_Up>(__new_val);
|
||||
return __old_val;
|
||||
}
|
||||
|
||||
/// @} group utilities
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#define _GLIBCXX_MOVE(__val) std::move(__val)
|
||||
#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val)
|
||||
#else
|
||||
#define _GLIBCXX_MOVE(__val) (__val)
|
||||
#define _GLIBCXX_FORWARD(_Tp, __val) (__val)
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Swaps two values.
|
||||
* @param __a A thing of arbitrary type.
|
||||
* @param __b Another thing of arbitrary type.
|
||||
* @return Nothing.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline
|
||||
#if __cplusplus >= 201103L
|
||||
typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
|
||||
is_move_constructible<_Tp>,
|
||||
is_move_assignable<_Tp>>::value>::type
|
||||
swap(_Tp& __a, _Tp& __b)
|
||||
noexcept(__and_<is_nothrow_move_constructible<_Tp>,
|
||||
is_nothrow_move_assignable<_Tp>>::value)
|
||||
#else
|
||||
void
|
||||
swap(_Tp& __a, _Tp& __b)
|
||||
#endif
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
|
||||
|
||||
_Tp __tmp = _GLIBCXX_MOVE(__a);
|
||||
__a = _GLIBCXX_MOVE(__b);
|
||||
__b = _GLIBCXX_MOVE(__tmp);
|
||||
}
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// DR 809. std::swap should be overloaded for array types.
|
||||
/// Swap the contents of two arrays.
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline
|
||||
#if __cplusplus >= 201103L
|
||||
typename enable_if<__is_swappable<_Tp>::value>::type
|
||||
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
|
||||
noexcept(__is_nothrow_swappable<_Tp>::value)
|
||||
#else
|
||||
void
|
||||
swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
|
||||
#endif
|
||||
{
|
||||
for (size_t __n = 0; __n < _Nm; ++__n)
|
||||
swap(__a[__n], __b[__n]);
|
||||
}
|
||||
|
||||
/// @} group utilities
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _MOVE_H */
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// Specific definitions for GNU/Linux -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/os_defines.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iosfwd}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_OS_DEFINES
|
||||
#define _GLIBCXX_OS_DEFINES 1
|
||||
|
||||
// System-specific #define, typedefs, corrections, etc, go here. This
|
||||
// file will come before all others.
|
||||
|
||||
// This keeps isanum, et al from being propagated as macros.
|
||||
#define __NO_CTYPE 1
|
||||
|
||||
#if 0 // No GlibC
|
||||
#include <features.h> // TODO
|
||||
|
||||
// Provide a declaration for the possibly deprecated gets function, as
|
||||
// glibc 2.15 and later does not declare gets for ISO C11 when
|
||||
// __GNU_SOURCE is defined.
|
||||
#if __GLIBC_PREREQ(2,15) && defined(_GNU_SOURCE)
|
||||
# undef _GLIBCXX_HAVE_GETS
|
||||
#endif
|
||||
|
||||
// Glibc 2.23 removed the obsolete isinf and isnan declarations. Check the
|
||||
// version dynamically in case it has changed since libstdc++ was configured.
|
||||
#define _GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC __GLIBC_PREREQ(2,23)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
// Default predicates for internal use -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2013-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file predefined_ops.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* You should not attempt to use it directly. @headername{algorithm}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_PREDEFINED_OPS_H
|
||||
#define _GLIBCXX_PREDEFINED_OPS_H 1
|
||||
|
||||
namespace __gnu_cxx
|
||||
{
|
||||
namespace __ops
|
||||
{
|
||||
struct _Iter_less_iter
|
||||
{
|
||||
template<typename _Iterator1, typename _Iterator2>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
bool
|
||||
operator()(_Iterator1 __it1, _Iterator2 __it2) const
|
||||
{ return *__it1 < *__it2; }
|
||||
};
|
||||
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
inline _Iter_less_iter
|
||||
__iter_less_iter()
|
||||
{ return _Iter_less_iter(); }
|
||||
|
||||
struct _Iter_less_val
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
constexpr _Iter_less_val() = default;
|
||||
#else
|
||||
_Iter_less_val() { }
|
||||
#endif
|
||||
|
||||
explicit
|
||||
_Iter_less_val(_Iter_less_iter) { }
|
||||
|
||||
template<typename _Iterator, typename _Value>
|
||||
bool
|
||||
operator()(_Iterator __it, _Value& __val) const
|
||||
{ return *__it < __val; }
|
||||
};
|
||||
|
||||
inline _Iter_less_val
|
||||
__iter_less_val()
|
||||
{ return _Iter_less_val(); }
|
||||
|
||||
inline _Iter_less_val
|
||||
__iter_comp_val(_Iter_less_iter)
|
||||
{ return _Iter_less_val(); }
|
||||
|
||||
struct _Val_less_iter
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
constexpr _Val_less_iter() = default;
|
||||
#else
|
||||
_Val_less_iter() { }
|
||||
#endif
|
||||
|
||||
explicit
|
||||
_Val_less_iter(_Iter_less_iter) { }
|
||||
|
||||
template<typename _Value, typename _Iterator>
|
||||
bool
|
||||
operator()(_Value& __val, _Iterator __it) const
|
||||
{ return __val < *__it; }
|
||||
};
|
||||
|
||||
inline _Val_less_iter
|
||||
__val_less_iter()
|
||||
{ return _Val_less_iter(); }
|
||||
|
||||
inline _Val_less_iter
|
||||
__val_comp_iter(_Iter_less_iter)
|
||||
{ return _Val_less_iter(); }
|
||||
|
||||
struct _Iter_equal_to_iter
|
||||
{
|
||||
template<typename _Iterator1, typename _Iterator2>
|
||||
bool
|
||||
operator()(_Iterator1 __it1, _Iterator2 __it2) const
|
||||
{ return *__it1 == *__it2; }
|
||||
};
|
||||
|
||||
inline _Iter_equal_to_iter
|
||||
__iter_equal_to_iter()
|
||||
{ return _Iter_equal_to_iter(); }
|
||||
|
||||
struct _Iter_equal_to_val
|
||||
{
|
||||
template<typename _Iterator, typename _Value>
|
||||
bool
|
||||
operator()(_Iterator __it, _Value& __val) const
|
||||
{ return *__it == __val; }
|
||||
};
|
||||
|
||||
inline _Iter_equal_to_val
|
||||
__iter_equal_to_val()
|
||||
{ return _Iter_equal_to_val(); }
|
||||
|
||||
inline _Iter_equal_to_val
|
||||
__iter_comp_val(_Iter_equal_to_iter)
|
||||
{ return _Iter_equal_to_val(); }
|
||||
|
||||
template<typename _Compare>
|
||||
struct _Iter_comp_iter
|
||||
{
|
||||
_Compare _M_comp;
|
||||
|
||||
explicit _GLIBCXX14_CONSTEXPR
|
||||
_Iter_comp_iter(_Compare __comp)
|
||||
: _M_comp(_GLIBCXX_MOVE(__comp))
|
||||
{ }
|
||||
|
||||
template<typename _Iterator1, typename _Iterator2>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
bool
|
||||
operator()(_Iterator1 __it1, _Iterator2 __it2)
|
||||
{ return bool(_M_comp(*__it1, *__it2)); }
|
||||
};
|
||||
|
||||
template<typename _Compare>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
inline _Iter_comp_iter<_Compare>
|
||||
__iter_comp_iter(_Compare __comp)
|
||||
{ return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
|
||||
|
||||
template<typename _Compare>
|
||||
struct _Iter_comp_val
|
||||
{
|
||||
_Compare _M_comp;
|
||||
|
||||
explicit
|
||||
_Iter_comp_val(_Compare __comp)
|
||||
: _M_comp(_GLIBCXX_MOVE(__comp))
|
||||
{ }
|
||||
|
||||
explicit
|
||||
_Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
|
||||
: _M_comp(__comp._M_comp)
|
||||
{ }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
explicit
|
||||
_Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
|
||||
: _M_comp(std::move(__comp._M_comp))
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template<typename _Iterator, typename _Value>
|
||||
bool
|
||||
operator()(_Iterator __it, _Value& __val)
|
||||
{ return bool(_M_comp(*__it, __val)); }
|
||||
};
|
||||
|
||||
template<typename _Compare>
|
||||
inline _Iter_comp_val<_Compare>
|
||||
__iter_comp_val(_Compare __comp)
|
||||
{ return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
|
||||
|
||||
template<typename _Compare>
|
||||
inline _Iter_comp_val<_Compare>
|
||||
__iter_comp_val(_Iter_comp_iter<_Compare> __comp)
|
||||
{ return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); }
|
||||
|
||||
template<typename _Compare>
|
||||
struct _Val_comp_iter
|
||||
{
|
||||
_Compare _M_comp;
|
||||
|
||||
explicit
|
||||
_Val_comp_iter(_Compare __comp)
|
||||
: _M_comp(_GLIBCXX_MOVE(__comp))
|
||||
{ }
|
||||
|
||||
explicit
|
||||
_Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp)
|
||||
: _M_comp(__comp._M_comp)
|
||||
{ }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
explicit
|
||||
_Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp)
|
||||
: _M_comp(std::move(__comp._M_comp))
|
||||
{ }
|
||||
#endif
|
||||
|
||||
template<typename _Value, typename _Iterator>
|
||||
bool
|
||||
operator()(_Value& __val, _Iterator __it)
|
||||
{ return bool(_M_comp(__val, *__it)); }
|
||||
};
|
||||
|
||||
template<typename _Compare>
|
||||
inline _Val_comp_iter<_Compare>
|
||||
__val_comp_iter(_Compare __comp)
|
||||
{ return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
|
||||
|
||||
template<typename _Compare>
|
||||
inline _Val_comp_iter<_Compare>
|
||||
__val_comp_iter(_Iter_comp_iter<_Compare> __comp)
|
||||
{ return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); }
|
||||
|
||||
template<typename _Value>
|
||||
struct _Iter_equals_val
|
||||
{
|
||||
_Value& _M_value;
|
||||
|
||||
explicit
|
||||
_Iter_equals_val(_Value& __value)
|
||||
: _M_value(__value)
|
||||
{ }
|
||||
|
||||
template<typename _Iterator>
|
||||
bool
|
||||
operator()(_Iterator __it)
|
||||
{ return *__it == _M_value; }
|
||||
};
|
||||
|
||||
template<typename _Value>
|
||||
inline _Iter_equals_val<_Value>
|
||||
__iter_equals_val(_Value& __val)
|
||||
{ return _Iter_equals_val<_Value>(__val); }
|
||||
|
||||
template<typename _Iterator1>
|
||||
struct _Iter_equals_iter
|
||||
{
|
||||
_Iterator1 _M_it1;
|
||||
|
||||
explicit
|
||||
_Iter_equals_iter(_Iterator1 __it1)
|
||||
: _M_it1(__it1)
|
||||
{ }
|
||||
|
||||
template<typename _Iterator2>
|
||||
bool
|
||||
operator()(_Iterator2 __it2)
|
||||
{ return *__it2 == *_M_it1; }
|
||||
};
|
||||
|
||||
template<typename _Iterator>
|
||||
inline _Iter_equals_iter<_Iterator>
|
||||
__iter_comp_iter(_Iter_equal_to_iter, _Iterator __it)
|
||||
{ return _Iter_equals_iter<_Iterator>(__it); }
|
||||
|
||||
template<typename _Predicate>
|
||||
struct _Iter_pred
|
||||
{
|
||||
_Predicate _M_pred;
|
||||
|
||||
explicit
|
||||
_Iter_pred(_Predicate __pred)
|
||||
: _M_pred(_GLIBCXX_MOVE(__pred))
|
||||
{ }
|
||||
|
||||
template<typename _Iterator>
|
||||
bool
|
||||
operator()(_Iterator __it)
|
||||
{ return bool(_M_pred(*__it)); }
|
||||
};
|
||||
|
||||
template<typename _Predicate>
|
||||
inline _Iter_pred<_Predicate>
|
||||
__pred_iter(_Predicate __pred)
|
||||
{ return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); }
|
||||
|
||||
template<typename _Compare, typename _Value>
|
||||
struct _Iter_comp_to_val
|
||||
{
|
||||
_Compare _M_comp;
|
||||
_Value& _M_value;
|
||||
|
||||
_Iter_comp_to_val(_Compare __comp, _Value& __value)
|
||||
: _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value)
|
||||
{ }
|
||||
|
||||
template<typename _Iterator>
|
||||
bool
|
||||
operator()(_Iterator __it)
|
||||
{ return bool(_M_comp(*__it, _M_value)); }
|
||||
};
|
||||
|
||||
template<typename _Compare, typename _Value>
|
||||
_Iter_comp_to_val<_Compare, _Value>
|
||||
__iter_comp_val(_Compare __comp, _Value &__val)
|
||||
{
|
||||
return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val);
|
||||
}
|
||||
|
||||
template<typename _Compare, typename _Iterator1>
|
||||
struct _Iter_comp_to_iter
|
||||
{
|
||||
_Compare _M_comp;
|
||||
_Iterator1 _M_it1;
|
||||
|
||||
_Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
|
||||
: _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1)
|
||||
{ }
|
||||
|
||||
template<typename _Iterator2>
|
||||
bool
|
||||
operator()(_Iterator2 __it2)
|
||||
{ return bool(_M_comp(*__it2, *_M_it1)); }
|
||||
};
|
||||
|
||||
template<typename _Compare, typename _Iterator>
|
||||
inline _Iter_comp_to_iter<_Compare, _Iterator>
|
||||
__iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
|
||||
{
|
||||
return _Iter_comp_to_iter<_Compare, _Iterator>(
|
||||
_GLIBCXX_MOVE(__comp._M_comp), __it);
|
||||
}
|
||||
|
||||
template<typename _Predicate>
|
||||
struct _Iter_negate
|
||||
{
|
||||
_Predicate _M_pred;
|
||||
|
||||
explicit
|
||||
_Iter_negate(_Predicate __pred)
|
||||
: _M_pred(_GLIBCXX_MOVE(__pred))
|
||||
{ }
|
||||
|
||||
template<typename _Iterator>
|
||||
bool
|
||||
operator()(_Iterator __it)
|
||||
{ return !bool(_M_pred(*__it)); }
|
||||
};
|
||||
|
||||
template<typename _Predicate>
|
||||
inline _Iter_negate<_Predicate>
|
||||
__negate(_Iter_pred<_Predicate> __pred)
|
||||
{ return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); }
|
||||
|
||||
} // namespace __ops
|
||||
} // namespace __gnu_cxx
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
// Pointer Traits -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/ptr_traits.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _PTR_TRAITS_H
|
||||
#define _PTR_TRAITS_H 1
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
#include "../bits/move.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
class __undefined;
|
||||
|
||||
// Given Template<T, ...> return T, otherwise invalid.
|
||||
template<typename _Tp>
|
||||
struct __get_first_arg
|
||||
{ using type = __undefined; };
|
||||
|
||||
template<template<typename, typename...> class _Template, typename _Tp,
|
||||
typename... _Types>
|
||||
struct __get_first_arg<_Template<_Tp, _Types...>>
|
||||
{ using type = _Tp; };
|
||||
|
||||
template<typename _Tp>
|
||||
using __get_first_arg_t = typename __get_first_arg<_Tp>::type;
|
||||
|
||||
// Given Template<T, ...> and U return Template<U, ...>, otherwise invalid.
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __replace_first_arg
|
||||
{ };
|
||||
|
||||
template<template<typename, typename...> class _Template, typename _Up,
|
||||
typename _Tp, typename... _Types>
|
||||
struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
|
||||
{ using type = _Template<_Up, _Types...>; };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type;
|
||||
|
||||
template<typename _Tp>
|
||||
using __make_not_void
|
||||
= typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type;
|
||||
|
||||
/**
|
||||
* @brief Uniform interface to all pointer-like types
|
||||
* @ingroup pointer_abstractions
|
||||
*/
|
||||
template<typename _Ptr>
|
||||
struct pointer_traits
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
using __element_type = typename _Tp::element_type;
|
||||
|
||||
template<typename _Tp>
|
||||
using __difference_type = typename _Tp::difference_type;
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __rebind : __replace_first_arg<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
|
||||
{ using type = typename _Tp::template rebind<_Up>; };
|
||||
|
||||
public:
|
||||
/// The pointer type.
|
||||
using pointer = _Ptr;
|
||||
|
||||
/// The type pointed to.
|
||||
using element_type
|
||||
= __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>;
|
||||
|
||||
/// The type used to represent the difference between two pointers.
|
||||
using difference_type
|
||||
= __detected_or_t<ptrdiff_t, __difference_type, _Ptr>;
|
||||
|
||||
/// A pointer to a different type.
|
||||
template<typename _Up>
|
||||
using rebind = typename __rebind<_Ptr, _Up>::type;
|
||||
|
||||
static _Ptr
|
||||
pointer_to(__make_not_void<element_type>& __e)
|
||||
{ return _Ptr::pointer_to(__e); }
|
||||
|
||||
static_assert(!is_same<element_type, __undefined>::value,
|
||||
"pointer type defines element_type or is like SomePointer<T, Args>");
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Partial specialization for built-in pointers.
|
||||
* @ingroup pointer_abstractions
|
||||
*/
|
||||
template<typename _Tp>
|
||||
struct pointer_traits<_Tp*>
|
||||
{
|
||||
/// The pointer type
|
||||
typedef _Tp* pointer;
|
||||
/// The type pointed to
|
||||
typedef _Tp element_type;
|
||||
/// Type used to represent the difference between two pointers
|
||||
typedef ptrdiff_t difference_type;
|
||||
|
||||
template<typename _Up>
|
||||
using rebind = _Up*;
|
||||
|
||||
/**
|
||||
* @brief Obtain a pointer to an object
|
||||
* @param __r A reference to an object of type @c element_type
|
||||
* @return @c addressof(__r)
|
||||
*/
|
||||
static pointer
|
||||
pointer_to(__make_not_void<element_type>& __r) noexcept
|
||||
{ return std::addressof(__r); }
|
||||
};
|
||||
|
||||
/// Convenience alias for rebinding pointers.
|
||||
template<typename _Ptr, typename _Tp>
|
||||
using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
// <range_access.h> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2010-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/range_access.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_RANGE_ACCESS_H
|
||||
#define _GLIBCXX_RANGE_ACCESS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../initializer_list"
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to the first element of
|
||||
* the container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
begin(_Container& __cont) -> decltype(__cont.begin())
|
||||
{ return __cont.begin(); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to the first element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
begin(const _Container& __cont) -> decltype(__cont.begin())
|
||||
{ return __cont.begin(); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to one past the last element of
|
||||
* the container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
end(_Container& __cont) -> decltype(__cont.end())
|
||||
{ return __cont.end(); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to one past the last element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
end(const _Container& __cont) -> decltype(__cont.end())
|
||||
{ return __cont.end(); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to the first element of the array.
|
||||
* @param __arr Array.
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX14_CONSTEXPR _Tp*
|
||||
begin(_Tp (&__arr)[_Nm])
|
||||
{ return __arr; }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to one past the last element
|
||||
* of the array.
|
||||
* @param __arr Array.
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX14_CONSTEXPR _Tp*
|
||||
end(_Tp (&__arr)[_Nm])
|
||||
{ return __arr + _Nm; }
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
template<typename _Tp> class valarray;
|
||||
// These overloads must be declared for cbegin and cend to use them.
|
||||
template<typename _Tp> _Tp* begin(valarray<_Tp>&);
|
||||
template<typename _Tp> const _Tp* begin(const valarray<_Tp>&);
|
||||
template<typename _Tp> _Tp* end(valarray<_Tp>&);
|
||||
template<typename _Tp> const _Tp* end(const valarray<_Tp>&);
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to the first element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline constexpr auto
|
||||
cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
|
||||
-> decltype(std::begin(__cont))
|
||||
{ return std::begin(__cont); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to one past the last element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline constexpr auto
|
||||
cend(const _Container& __cont) noexcept(noexcept(std::end(__cont)))
|
||||
-> decltype(std::end(__cont))
|
||||
{ return std::end(__cont); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing to the last element of
|
||||
* the container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
rbegin(_Container& __cont) -> decltype(__cont.rbegin())
|
||||
{ return __cont.rbegin(); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing to the last element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
rbegin(const _Container& __cont) -> decltype(__cont.rbegin())
|
||||
{ return __cont.rbegin(); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing one past the first element of
|
||||
* the container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
rend(_Container& __cont) -> decltype(__cont.rend())
|
||||
{ return __cont.rend(); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing one past the first element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
rend(const _Container& __cont) -> decltype(__cont.rend())
|
||||
{ return __cont.rend(); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing to the last element of
|
||||
* the array.
|
||||
* @param __arr Array.
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
|
||||
rbegin(_Tp (&__arr)[_Nm])
|
||||
{ return reverse_iterator<_Tp*>(__arr + _Nm); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing one past the first element of
|
||||
* the array.
|
||||
* @param __arr Array.
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
|
||||
rend(_Tp (&__arr)[_Nm])
|
||||
{ return reverse_iterator<_Tp*>(__arr); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing to the last element of
|
||||
* the initializer_list.
|
||||
* @param __il initializer_list.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
|
||||
rbegin(initializer_list<_Tp> __il)
|
||||
{ return reverse_iterator<const _Tp*>(__il.end()); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing one past the first element of
|
||||
* the initializer_list.
|
||||
* @param __il initializer_list.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
|
||||
rend(initializer_list<_Tp> __il)
|
||||
{ return reverse_iterator<const _Tp*>(__il.begin()); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing to the last element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont))
|
||||
{ return std::rbegin(__cont); }
|
||||
|
||||
/**
|
||||
* @brief Return a reverse iterator pointing one past the first element of
|
||||
* the const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template<typename _Container>
|
||||
inline _GLIBCXX17_CONSTEXPR auto
|
||||
crend(const _Container& __cont) -> decltype(std::rend(__cont))
|
||||
{ return std::rend(__cont); }
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define __cpp_lib_nonmember_container_access 201411
|
||||
|
||||
/**
|
||||
* @brief Return the size of a container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
size(const _Container& __cont) noexcept(noexcept(__cont.size()))
|
||||
-> decltype(__cont.size())
|
||||
{ return __cont.size(); }
|
||||
|
||||
/**
|
||||
* @brief Return the size of an array.
|
||||
* @param __array Array.
|
||||
*/
|
||||
template <typename _Tp, size_t _Nm>
|
||||
constexpr size_t
|
||||
size(const _Tp (&/*__array*/)[_Nm]) noexcept
|
||||
{ return _Nm; }
|
||||
|
||||
/**
|
||||
* @brief Return whether a container is empty.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
empty(const _Container& __cont) noexcept(noexcept(__cont.empty()))
|
||||
-> decltype(__cont.empty())
|
||||
{ return __cont.empty(); }
|
||||
|
||||
/**
|
||||
* @brief Return whether an array is empty (always false).
|
||||
* @param __array Container.
|
||||
*/
|
||||
template <typename _Tp, size_t _Nm>
|
||||
constexpr bool
|
||||
empty(const _Tp (&/*__array*/)[_Nm]) noexcept
|
||||
{ return false; }
|
||||
|
||||
/**
|
||||
* @brief Return whether an initializer_list is empty.
|
||||
* @param __il Initializer list.
|
||||
*/
|
||||
template <typename _Tp>
|
||||
constexpr bool
|
||||
empty(initializer_list<_Tp> __il) noexcept
|
||||
{ return __il.size() == 0;}
|
||||
|
||||
/**
|
||||
* @brief Return the data pointer of a container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
data(_Container& __cont) noexcept(noexcept(__cont.data()))
|
||||
-> decltype(__cont.data())
|
||||
{ return __cont.data(); }
|
||||
|
||||
/**
|
||||
* @brief Return the data pointer of a const container.
|
||||
* @param __cont Container.
|
||||
*/
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
data(const _Container& __cont) noexcept(noexcept(__cont.data()))
|
||||
-> decltype(__cont.data())
|
||||
{ return __cont.data(); }
|
||||
|
||||
/**
|
||||
* @brief Return the data pointer of an array.
|
||||
* @param __array Array.
|
||||
*/
|
||||
template <typename _Tp, size_t _Nm>
|
||||
constexpr _Tp*
|
||||
data(_Tp (&__array)[_Nm]) noexcept
|
||||
{ return __array; }
|
||||
|
||||
/**
|
||||
* @brief Return the data pointer of an initializer list.
|
||||
* @param __il Initializer list.
|
||||
*/
|
||||
template <typename _Tp>
|
||||
constexpr const _Tp*
|
||||
data(initializer_list<_Tp> __il) noexcept
|
||||
{ return __il.begin(); }
|
||||
|
||||
#endif // C++17
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _GLIBCXX_RANGE_ACCESS_H
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// -*- C++ -*- C library enhancements header.
|
||||
|
||||
// Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/bits/std_abs.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{cmath, cstdlib}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_BITS_STD_ABS_H
|
||||
#define _GLIBCXX_BITS_STD_ABS_H
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
#include_next <stdlib.h>
|
||||
#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO
|
||||
# include_next <math.h>
|
||||
#endif
|
||||
#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
|
||||
#undef abs
|
||||
|
||||
extern "C++"
|
||||
{
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
using ::abs;
|
||||
|
||||
#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO
|
||||
inline long
|
||||
abs(long __i) { return __builtin_labs(__i); }
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_USE_LONG_LONG
|
||||
inline long long
|
||||
abs(long long __x) { return __builtin_llabs (__x); }
|
||||
#endif
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2192. Validity and return type of std::abs(0u) is unclear
|
||||
// 2294. <cstdlib> should declare abs(double)
|
||||
|
||||
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
|
||||
inline _GLIBCXX_CONSTEXPR double
|
||||
abs(double __x)
|
||||
{ return __builtin_fabs(__x); }
|
||||
|
||||
inline _GLIBCXX_CONSTEXPR float
|
||||
abs(float __x)
|
||||
{ return __builtin_fabsf(__x); }
|
||||
|
||||
inline _GLIBCXX_CONSTEXPR long double
|
||||
abs(long double __x)
|
||||
{ return __builtin_fabsl(__x); }
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_0)
|
||||
inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0
|
||||
abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; }
|
||||
#endif
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_1)
|
||||
inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1
|
||||
abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; }
|
||||
#endif
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_2)
|
||||
inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2
|
||||
abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; }
|
||||
#endif
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_3)
|
||||
inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3
|
||||
abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; }
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) && !defined(__CUDACC__)
|
||||
inline _GLIBCXX_CONSTEXPR
|
||||
__float128
|
||||
abs(__float128 __x)
|
||||
{ return __x < 0 ? -__x : __x; }
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
}
|
||||
|
||||
#endif // _GLIBCXX_BITS_STD_ABS_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,235 @@
|
|||
// nonstandard construct and destroy functions -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_construct.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _STL_CONSTRUCT_H
|
||||
#define _STL_CONSTRUCT_H 1
|
||||
|
||||
#include "../new"
|
||||
#include "../bits/move.h"
|
||||
#include "../ext/alloc_traits.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* Constructs an object in existing memory by invoking an allocated
|
||||
* object's constructor with an initializer.
|
||||
*/
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _T1, typename... _Args>
|
||||
inline void
|
||||
_Construct(_T1* __p, _Args&&... __args)
|
||||
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
|
||||
#else
|
||||
template<typename _T1, typename _T2>
|
||||
inline void
|
||||
_Construct(_T1* __p, const _T2& __value)
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 402. wrong new expression in [some_]allocator::construct
|
||||
::new(static_cast<void*>(__p)) _T1(__value);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _T1>
|
||||
inline void
|
||||
_Construct_novalue(_T1* __p)
|
||||
{ ::new(static_cast<void*>(__p)) _T1; }
|
||||
|
||||
/**
|
||||
* Destroy the object pointed to by a pointer type.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline void
|
||||
_Destroy(_Tp* __pointer)
|
||||
{ __pointer->~_Tp(); }
|
||||
|
||||
template<bool>
|
||||
struct _Destroy_aux
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__destroy(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
std::_Destroy(std::__addressof(*__first));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _Destroy_aux<true>
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__destroy(_ForwardIterator, _ForwardIterator) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy a range of objects. If the value_type of the object has
|
||||
* a trivial destructor, the compiler should optimize all of this
|
||||
* away, otherwise the objects' destructors must be invoked.
|
||||
*/
|
||||
template<typename _ForwardIterator>
|
||||
inline void
|
||||
_Destroy(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_Value_type;
|
||||
#if __cplusplus >= 201103L
|
||||
// A deleted destructor is trivial, this ensures we reject such types:
|
||||
static_assert(is_destructible<_Value_type>::value,
|
||||
"value type is destructible");
|
||||
#endif
|
||||
std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
|
||||
__destroy(__first, __last);
|
||||
}
|
||||
|
||||
template<bool>
|
||||
struct _Destroy_n_aux
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__destroy_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
for (; __count > 0; (void)++__first, --__count)
|
||||
std::_Destroy(std::__addressof(*__first));
|
||||
return __first;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _Destroy_n_aux<true>
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__destroy_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
std::advance(__first, __count);
|
||||
return __first;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy a range of objects. If the value_type of the object has
|
||||
* a trivial destructor, the compiler should optimize all of this
|
||||
* away, otherwise the objects' destructors must be invoked.
|
||||
*/
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
_Destroy_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_Value_type;
|
||||
#if __cplusplus >= 201103L
|
||||
// A deleted destructor is trivial, this ensures we reject such types:
|
||||
static_assert(is_destructible<_Value_type>::value,
|
||||
"value type is destructible");
|
||||
#endif
|
||||
return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
|
||||
__destroy_n(__first, __count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a range of objects using the supplied allocator. For
|
||||
* nondefault allocators we do not optimize away invocation of
|
||||
* destroy() even if _Tp has a trivial destructor.
|
||||
*/
|
||||
|
||||
template<typename _ForwardIterator, typename _Allocator>
|
||||
void
|
||||
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __first != __last; ++__first)
|
||||
__traits::destroy(__alloc, std::__addressof(*__first));
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
inline void
|
||||
_Destroy(_ForwardIterator __first, _ForwardIterator __last,
|
||||
allocator<_Tp>&)
|
||||
{
|
||||
_Destroy(__first, __last);
|
||||
}
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template <typename _Tp>
|
||||
inline void
|
||||
destroy_at(_Tp* __location)
|
||||
{
|
||||
std::_Destroy(__location);
|
||||
}
|
||||
|
||||
template <typename _ForwardIterator>
|
||||
inline void
|
||||
destroy(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
std::_Destroy(__first, __last);
|
||||
}
|
||||
|
||||
template <typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
destroy_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
return std::_Destroy_n(__first, __count);
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif /* _STL_CONSTRUCT_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,561 @@
|
|||
// Heap implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Copyright (c) 1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_heap.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{queue}
|
||||
*/
|
||||
|
||||
#ifndef _STL_HEAP_H
|
||||
#define _STL_HEAP_H 1
|
||||
|
||||
#include "../debug/debug.h"
|
||||
#include "../bits/move.h"
|
||||
#include "../bits/predefined_ops.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @defgroup heap_algorithms Heap
|
||||
* @ingroup sorting_algorithms
|
||||
*/
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Distance,
|
||||
typename _Compare>
|
||||
_Distance
|
||||
__is_heap_until(_RandomAccessIterator __first, _Distance __n,
|
||||
_Compare& __comp)
|
||||
{
|
||||
_Distance __parent = 0;
|
||||
for (_Distance __child = 1; __child < __n; ++__child)
|
||||
{
|
||||
if (__comp(__first + __parent, __first + __child))
|
||||
return __child;
|
||||
if ((__child & 1) == 0)
|
||||
++__parent;
|
||||
}
|
||||
return __n;
|
||||
}
|
||||
|
||||
// __is_heap, a predicate testing whether or not a range is a heap.
|
||||
// This function is an extension, not part of the C++ standard.
|
||||
template<typename _RandomAccessIterator, typename _Distance>
|
||||
inline bool
|
||||
__is_heap(_RandomAccessIterator __first, _Distance __n)
|
||||
{
|
||||
__gnu_cxx::__ops::_Iter_less_iter __comp;
|
||||
return std::__is_heap_until(__first, __n, __comp) == __n;
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Compare,
|
||||
typename _Distance>
|
||||
inline bool
|
||||
__is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
|
||||
{
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
return std::__is_heap_until(__first, __n, __cmp) == __n;
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator>
|
||||
inline bool
|
||||
__is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{ return std::__is_heap(__first, std::distance(__first, __last)); }
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline bool
|
||||
__is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
|
||||
std::distance(__first, __last));
|
||||
}
|
||||
|
||||
// Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
|
||||
// + is_heap and is_heap_until in C++0x.
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
|
||||
typename _Compare>
|
||||
void
|
||||
__push_heap(_RandomAccessIterator __first,
|
||||
_Distance __holeIndex, _Distance __topIndex, _Tp __value,
|
||||
_Compare& __comp)
|
||||
{
|
||||
_Distance __parent = (__holeIndex - 1) / 2;
|
||||
while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
|
||||
{
|
||||
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
|
||||
__holeIndex = __parent;
|
||||
__parent = (__holeIndex - 1) / 2;
|
||||
}
|
||||
*(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push an element onto a heap.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap + element.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation pushes the element at last-1 onto the valid heap
|
||||
* over the range [__first,__last-1). After completion,
|
||||
* [__first,__last) is a valid heap.
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline void
|
||||
push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::value_type
|
||||
_ValueType;
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
|
||||
_DistanceType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive(__first, __last);
|
||||
__glibcxx_requires_heap(__first, __last - 1);
|
||||
|
||||
__gnu_cxx::__ops::_Iter_less_val __comp;
|
||||
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
|
||||
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
|
||||
_DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push an element onto a heap using comparison functor.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap + element.
|
||||
* @param __comp Comparison functor.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation pushes the element at __last-1 onto the valid
|
||||
* heap over the range [__first,__last-1). After completion,
|
||||
* [__first,__last) is a valid heap. Compare operations are
|
||||
* performed using comp.
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline void
|
||||
push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::value_type
|
||||
_ValueType;
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
|
||||
_DistanceType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
__glibcxx_requires_heap_pred(__first, __last - 1, __comp);
|
||||
|
||||
__decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
|
||||
__cmp(_GLIBCXX_MOVE(__comp));
|
||||
_ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
|
||||
std::__push_heap(__first, _DistanceType((__last - __first) - 1),
|
||||
_DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Distance,
|
||||
typename _Tp, typename _Compare>
|
||||
void
|
||||
__adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
|
||||
_Distance __len, _Tp __value, _Compare __comp)
|
||||
{
|
||||
const _Distance __topIndex = __holeIndex;
|
||||
_Distance __secondChild = __holeIndex;
|
||||
while (__secondChild < (__len - 1) / 2)
|
||||
{
|
||||
__secondChild = 2 * (__secondChild + 1);
|
||||
if (__comp(__first + __secondChild,
|
||||
__first + (__secondChild - 1)))
|
||||
__secondChild--;
|
||||
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
|
||||
__holeIndex = __secondChild;
|
||||
}
|
||||
if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
|
||||
{
|
||||
__secondChild = 2 * (__secondChild + 1);
|
||||
*(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
|
||||
+ (__secondChild - 1)));
|
||||
__holeIndex = __secondChild - 1;
|
||||
}
|
||||
__decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
|
||||
__cmp(_GLIBCXX_MOVE(__comp));
|
||||
std::__push_heap(__first, __holeIndex, __topIndex,
|
||||
_GLIBCXX_MOVE(__value), __cmp);
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline void
|
||||
__pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_RandomAccessIterator __result, _Compare& __comp)
|
||||
{
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::value_type
|
||||
_ValueType;
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
|
||||
_DistanceType;
|
||||
|
||||
_ValueType __value = _GLIBCXX_MOVE(*__result);
|
||||
*__result = _GLIBCXX_MOVE(*__first);
|
||||
std::__adjust_heap(__first, _DistanceType(0),
|
||||
_DistanceType(__last - __first),
|
||||
_GLIBCXX_MOVE(__value), __comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pop an element off a heap.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @pre [__first, __last) is a valid, non-empty range.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation pops the top of the heap. The elements __first
|
||||
* and __last-1 are swapped and [__first,__last-1) is made into a
|
||||
* heap.
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline void
|
||||
pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_function_requires(_LessThanComparableConcept<
|
||||
typename iterator_traits<_RandomAccessIterator>::value_type>)
|
||||
__glibcxx_requires_non_empty_range(__first, __last);
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive(__first, __last);
|
||||
__glibcxx_requires_heap(__first, __last);
|
||||
|
||||
if (__last - __first > 1)
|
||||
{
|
||||
--__last;
|
||||
__gnu_cxx::__ops::_Iter_less_iter __comp;
|
||||
std::__pop_heap(__first, __last, __last, __comp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pop an element off a heap using comparison functor.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @param __comp Comparison functor to use.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation pops the top of the heap. The elements __first
|
||||
* and __last-1 are swapped and [__first,__last-1) is made into a
|
||||
* heap. Comparisons are made using comp.
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline void
|
||||
pop_heap(_RandomAccessIterator __first,
|
||||
_RandomAccessIterator __last, _Compare __comp)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
__glibcxx_requires_non_empty_range(__first, __last);
|
||||
__glibcxx_requires_heap_pred(__first, __last, __comp);
|
||||
|
||||
if (__last - __first > 1)
|
||||
{
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
--__last;
|
||||
std::__pop_heap(__first, __last, __last, __cmp);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
void
|
||||
__make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare& __comp)
|
||||
{
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::value_type
|
||||
_ValueType;
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type
|
||||
_DistanceType;
|
||||
|
||||
if (__last - __first < 2)
|
||||
return;
|
||||
|
||||
const _DistanceType __len = __last - __first;
|
||||
_DistanceType __parent = (__len - 2) / 2;
|
||||
while (true)
|
||||
{
|
||||
_ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
|
||||
std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
|
||||
__comp);
|
||||
if (__parent == 0)
|
||||
return;
|
||||
__parent--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a heap over a range.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation makes the elements in [__first,__last) into a heap.
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline void
|
||||
make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_function_requires(_LessThanComparableConcept<
|
||||
typename iterator_traits<_RandomAccessIterator>::value_type>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive(__first, __last);
|
||||
|
||||
__gnu_cxx::__ops::_Iter_less_iter __comp;
|
||||
std::__make_heap(__first, __last, __comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a heap over a range using comparison functor.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @param __comp Comparison functor to use.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation makes the elements in [__first,__last) into a heap.
|
||||
* Comparisons are made using __comp.
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline void
|
||||
make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
std::__make_heap(__first, __last, __cmp);
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
void
|
||||
__sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare& __comp)
|
||||
{
|
||||
while (__last - __first > 1)
|
||||
{
|
||||
--__last;
|
||||
std::__pop_heap(__first, __last, __last, __comp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sort a heap.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation sorts the valid heap in the range [__first,__last).
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline void
|
||||
sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_function_requires(_LessThanComparableConcept<
|
||||
typename iterator_traits<_RandomAccessIterator>::value_type>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive(__first, __last);
|
||||
__glibcxx_requires_heap(__first, __last);
|
||||
|
||||
__gnu_cxx::__ops::_Iter_less_iter __comp;
|
||||
std::__sort_heap(__first, __last, __comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sort a heap using comparison functor.
|
||||
* @param __first Start of heap.
|
||||
* @param __last End of heap.
|
||||
* @param __comp Comparison functor to use.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation sorts the valid heap in the range [__first,__last).
|
||||
* Comparisons are made using __comp.
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline void
|
||||
sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
__glibcxx_requires_heap_pred(__first, __last, __comp);
|
||||
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
std::__sort_heap(__first, __last, __cmp);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/**
|
||||
* @brief Search the end of a heap.
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @return An iterator pointing to the first element not in the heap.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation returns the last iterator i in [__first, __last) for which
|
||||
* the range [__first, i) is a heap.
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline _RandomAccessIterator
|
||||
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_function_requires(_LessThanComparableConcept<
|
||||
typename iterator_traits<_RandomAccessIterator>::value_type>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive(__first, __last);
|
||||
|
||||
__gnu_cxx::__ops::_Iter_less_iter __comp;
|
||||
return __first +
|
||||
std::__is_heap_until(__first, std::distance(__first, __last), __comp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Search the end of a heap using comparison functor.
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @param __comp Comparison functor to use.
|
||||
* @return An iterator pointing to the first element not in the heap.
|
||||
* @ingroup heap_algorithms
|
||||
*
|
||||
* This operation returns the last iterator i in [__first, __last) for which
|
||||
* the range [__first, i) is a heap. Comparisons are made using __comp.
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline _RandomAccessIterator
|
||||
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
return __first
|
||||
+ std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines whether a range is a heap.
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @return True if range is a heap, false otherwise.
|
||||
* @ingroup heap_algorithms
|
||||
*/
|
||||
template<typename _RandomAccessIterator>
|
||||
inline bool
|
||||
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
|
||||
{ return std::is_heap_until(__first, __last) == __last; }
|
||||
|
||||
/**
|
||||
* @brief Determines whether a range is a heap using comparison functor.
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @param __comp Comparison functor to use.
|
||||
* @return True if range is a heap, false otherwise.
|
||||
* @ingroup heap_algorithms
|
||||
*/
|
||||
template<typename _RandomAccessIterator, typename _Compare>
|
||||
inline bool
|
||||
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
_Compare __comp)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);
|
||||
|
||||
const auto __dist = std::distance(__first, __last);
|
||||
typedef __decltype(__comp) _Cmp;
|
||||
__gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
|
||||
return std::__is_heap_until(__first, __dist, __cmp) == __dist;
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _STL_HEAP_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,235 @@
|
|||
// Functions used by iterators -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996-1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_iterator_base_funcs.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*
|
||||
* This file contains all of the general iterator-related utility
|
||||
* functions, such as distance() and advance().
|
||||
*/
|
||||
|
||||
#ifndef _STL_ITERATOR_BASE_FUNCS_H
|
||||
#define _STL_ITERATOR_BASE_FUNCS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/concept_check.h"
|
||||
// #include <debug/assertions.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
// Forward declaration for the overloads of __distance.
|
||||
template <typename> struct _List_iterator;
|
||||
template <typename> struct _List_const_iterator;
|
||||
_GLIBCXX_END_NAMESPACE_CONTAINER
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _InputIterator>
|
||||
inline _GLIBCXX14_CONSTEXPR
|
||||
typename iterator_traits<_InputIterator>::difference_type
|
||||
__distance(_InputIterator __first, _InputIterator __last,
|
||||
input_iterator_tag)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
|
||||
typename iterator_traits<_InputIterator>::difference_type __n = 0;
|
||||
while (__first != __last)
|
||||
{
|
||||
++__first;
|
||||
++__n;
|
||||
}
|
||||
return __n;
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator>
|
||||
inline _GLIBCXX14_CONSTEXPR
|
||||
typename iterator_traits<_RandomAccessIterator>::difference_type
|
||||
__distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
|
||||
random_access_iterator_tag)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
return __last - __first;
|
||||
}
|
||||
|
||||
#if _GLIBCXX_USE_CXX11_ABI
|
||||
// Forward declaration because of the qualified call in distance.
|
||||
template<typename _Tp>
|
||||
ptrdiff_t
|
||||
__distance(_GLIBCXX_STD_C::_List_iterator<_Tp>,
|
||||
_GLIBCXX_STD_C::_List_iterator<_Tp>,
|
||||
input_iterator_tag);
|
||||
|
||||
template<typename _Tp>
|
||||
ptrdiff_t
|
||||
__distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
|
||||
_GLIBCXX_STD_C::_List_const_iterator<_Tp>,
|
||||
input_iterator_tag);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A generalization of pointer arithmetic.
|
||||
* @param __first An input iterator.
|
||||
* @param __last An input iterator.
|
||||
* @return The distance between them.
|
||||
*
|
||||
* Returns @c n such that __first + n == __last. This requires
|
||||
* that @p __last must be reachable from @p __first. Note that @c
|
||||
* n may be negative.
|
||||
*
|
||||
* For random access iterators, this uses their @c + and @c - operations
|
||||
* and are constant time. For other %iterator classes they are linear time.
|
||||
*/
|
||||
template<typename _InputIterator>
|
||||
inline _GLIBCXX17_CONSTEXPR
|
||||
typename iterator_traits<_InputIterator>::difference_type
|
||||
distance(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
// concept requirements -- taken care of in __distance
|
||||
return std::__distance(__first, __last,
|
||||
std::__iterator_category(__first));
|
||||
}
|
||||
|
||||
template<typename _InputIterator, typename _Distance>
|
||||
inline _GLIBCXX14_CONSTEXPR void
|
||||
__advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_assert(__n >= 0);
|
||||
while (__n--)
|
||||
++__i;
|
||||
}
|
||||
|
||||
template<typename _BidirectionalIterator, typename _Distance>
|
||||
inline _GLIBCXX14_CONSTEXPR void
|
||||
__advance(_BidirectionalIterator& __i, _Distance __n,
|
||||
bidirectional_iterator_tag)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_BidirectionalIteratorConcept<
|
||||
_BidirectionalIterator>)
|
||||
if (__n > 0)
|
||||
while (__n--)
|
||||
++__i;
|
||||
else
|
||||
while (__n++)
|
||||
--__i;
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Distance>
|
||||
inline _GLIBCXX14_CONSTEXPR void
|
||||
__advance(_RandomAccessIterator& __i, _Distance __n,
|
||||
random_access_iterator_tag)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_RandomAccessIteratorConcept<
|
||||
_RandomAccessIterator>)
|
||||
__i += __n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A generalization of pointer arithmetic.
|
||||
* @param __i An input iterator.
|
||||
* @param __n The @a delta by which to change @p __i.
|
||||
* @return Nothing.
|
||||
*
|
||||
* This increments @p i by @p n. For bidirectional and random access
|
||||
* iterators, @p __n may be negative, in which case @p __i is decremented.
|
||||
*
|
||||
* For random access iterators, this uses their @c + and @c - operations
|
||||
* and are constant time. For other %iterator classes they are linear time.
|
||||
*/
|
||||
template<typename _InputIterator, typename _Distance>
|
||||
inline _GLIBCXX17_CONSTEXPR void
|
||||
advance(_InputIterator& __i, _Distance __n)
|
||||
{
|
||||
// concept requirements -- taken care of in __advance
|
||||
typename iterator_traits<_InputIterator>::difference_type __d = __n;
|
||||
std::__advance(__i, __d, std::__iterator_category(__i));
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
template<typename _ForwardIterator>
|
||||
inline _GLIBCXX17_CONSTEXPR _ForwardIterator
|
||||
next(_ForwardIterator __x, typename
|
||||
iterator_traits<_ForwardIterator>::difference_type __n = 1)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_ForwardIteratorConcept<
|
||||
_ForwardIterator>)
|
||||
std::advance(__x, __n);
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<typename _BidirectionalIterator>
|
||||
inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator
|
||||
prev(_BidirectionalIterator __x, typename
|
||||
iterator_traits<_BidirectionalIterator>::difference_type __n = 1)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_BidirectionalIteratorConcept<
|
||||
_BidirectionalIterator>)
|
||||
std::advance(__x, -__n);
|
||||
return __x;
|
||||
}
|
||||
|
||||
#endif // C++11
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _STL_ITERATOR_BASE_FUNCS_H */
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
// Types used in iterator implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996-1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_iterator_base_types.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*
|
||||
* This file contains all of the general iterator-related utility types,
|
||||
* such as iterator_traits and struct iterator.
|
||||
*/
|
||||
|
||||
#ifndef _STL_ITERATOR_BASE_TYPES_H
|
||||
#define _STL_ITERATOR_BASE_TYPES_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
# include "../type_traits" // For __void_t, is_convertible
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @defgroup iterators Iterators
|
||||
* Abstractions for uniform iterating through various underlying types.
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* @defgroup iterator_tags Iterator Tags
|
||||
* These are empty types, used to distinguish different iterators. The
|
||||
* distinction is not made by what they contain, but simply by what they
|
||||
* are. Different underlying algorithms can then be used based on the
|
||||
* different operations supported by different iterator types.
|
||||
*/
|
||||
//@{
|
||||
/// Marking input iterators.
|
||||
struct input_iterator_tag { };
|
||||
|
||||
/// Marking output iterators.
|
||||
struct output_iterator_tag { };
|
||||
|
||||
/// Forward iterators support a superset of input iterator operations.
|
||||
struct forward_iterator_tag : public input_iterator_tag { };
|
||||
|
||||
/// Bidirectional iterators support a superset of forward iterator
|
||||
/// operations.
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag { };
|
||||
|
||||
/// Random-access iterators support a superset of bidirectional
|
||||
/// iterator operations.
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @brief Common %iterator class.
|
||||
*
|
||||
* This class does nothing but define nested typedefs. %Iterator classes
|
||||
* can inherit from this class to save some work. The typedefs are then
|
||||
* used in specializations and overloading.
|
||||
*
|
||||
* In particular, there are no default implementations of requirements
|
||||
* such as @c operator++ and the like. (How could there be?)
|
||||
*/
|
||||
template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t,
|
||||
typename _Pointer = _Tp*, typename _Reference = _Tp&>
|
||||
struct iterator
|
||||
{
|
||||
/// One of the @link iterator_tags tag types@endlink.
|
||||
typedef _Category iterator_category;
|
||||
/// The type "pointed to" by the iterator.
|
||||
typedef _Tp value_type;
|
||||
/// Distance between iterators is represented as this type.
|
||||
typedef _Distance difference_type;
|
||||
/// This type represents a pointer-to-value_type.
|
||||
typedef _Pointer pointer;
|
||||
/// This type represents a reference-to-value_type.
|
||||
typedef _Reference reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Traits class for iterators.
|
||||
*
|
||||
* This class does nothing but define nested typedefs. The general
|
||||
* version simply @a forwards the nested typedefs from the Iterator
|
||||
* argument. Specialized versions for pointers and pointers-to-const
|
||||
* provide tighter, more correct semantics.
|
||||
*/
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14
|
||||
template<typename _Iterator, typename = __void_t<>>
|
||||
struct __iterator_traits { };
|
||||
|
||||
template<typename _Iterator>
|
||||
struct __iterator_traits<_Iterator,
|
||||
__void_t<typename _Iterator::iterator_category,
|
||||
typename _Iterator::value_type,
|
||||
typename _Iterator::difference_type,
|
||||
typename _Iterator::pointer,
|
||||
typename _Iterator::reference>>
|
||||
{
|
||||
typedef typename _Iterator::iterator_category iterator_category;
|
||||
typedef typename _Iterator::value_type value_type;
|
||||
typedef typename _Iterator::difference_type difference_type;
|
||||
typedef typename _Iterator::pointer pointer;
|
||||
typedef typename _Iterator::reference reference;
|
||||
};
|
||||
|
||||
template<typename _Iterator>
|
||||
struct iterator_traits
|
||||
: public __iterator_traits<_Iterator> { };
|
||||
#else
|
||||
template<typename _Iterator>
|
||||
struct iterator_traits
|
||||
{
|
||||
typedef typename _Iterator::iterator_category iterator_category;
|
||||
typedef typename _Iterator::value_type value_type;
|
||||
typedef typename _Iterator::difference_type difference_type;
|
||||
typedef typename _Iterator::pointer pointer;
|
||||
typedef typename _Iterator::reference reference;
|
||||
};
|
||||
#endif
|
||||
|
||||
/// Partial specialization for pointer types.
|
||||
template<typename _Tp>
|
||||
struct iterator_traits<_Tp*>
|
||||
{
|
||||
typedef random_access_iterator_tag iterator_category;
|
||||
typedef _Tp value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef _Tp* pointer;
|
||||
typedef _Tp& reference;
|
||||
};
|
||||
|
||||
/// Partial specialization for const pointer types.
|
||||
template<typename _Tp>
|
||||
struct iterator_traits<const _Tp*>
|
||||
{
|
||||
typedef random_access_iterator_tag iterator_category;
|
||||
typedef _Tp value_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef const _Tp* pointer;
|
||||
typedef const _Tp& reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function is not a part of the C++ standard but is syntactic
|
||||
* sugar for internal library use only.
|
||||
*/
|
||||
template<typename _Iter>
|
||||
inline _GLIBCXX_CONSTEXPR
|
||||
typename iterator_traits<_Iter>::iterator_category
|
||||
__iterator_category(const _Iter&)
|
||||
{ return typename iterator_traits<_Iter>::iterator_category(); }
|
||||
|
||||
//@}
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// If _Iterator has a base returns it otherwise _Iterator is returned
|
||||
// untouched
|
||||
template<typename _Iterator, bool _HasBase>
|
||||
struct _Iter_base
|
||||
{
|
||||
typedef _Iterator iterator_type;
|
||||
static iterator_type _S_base(_Iterator __it)
|
||||
{ return __it; }
|
||||
};
|
||||
|
||||
template<typename _Iterator>
|
||||
struct _Iter_base<_Iterator, true>
|
||||
{
|
||||
typedef typename _Iterator::iterator_type iterator_type;
|
||||
static iterator_type _S_base(_Iterator __it)
|
||||
{ return __it.base(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _InIter>
|
||||
using _RequireInputIter = typename
|
||||
enable_if<is_convertible<typename
|
||||
iterator_traits<_InIter>::iterator_category,
|
||||
input_iterator_tag>::value>::type;
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _STL_ITERATOR_BASE_TYPES_H */
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
// Numeric functions implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_numeric.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{numeric}
|
||||
*/
|
||||
|
||||
#ifndef _STL_NUMERIC_H
|
||||
#define _STL_NUMERIC_H 1
|
||||
|
||||
#include "../bits/concept_check.h"
|
||||
#include "../debug/debug.h"
|
||||
#include "../bits/move.h" // For _GLIBCXX_MOVE
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Create a range of sequentially increasing values.
|
||||
*
|
||||
* For each element in the range @p [first,last) assigns @p value and
|
||||
* increments @p value as if by @p ++value.
|
||||
*
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @param __value Starting value.
|
||||
* @return Nothing.
|
||||
*/
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
void
|
||||
iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
|
||||
_ForwardIterator>)
|
||||
__glibcxx_function_requires(_ConvertibleConcept<_Tp,
|
||||
typename iterator_traits<_ForwardIterator>::value_type>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
for (; __first != __last; ++__first)
|
||||
{
|
||||
*__first = __value;
|
||||
++__value;
|
||||
}
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_ALGO
|
||||
|
||||
/**
|
||||
* @brief Accumulate values in a range.
|
||||
*
|
||||
* Accumulates the values in the range [first,last) using operator+(). The
|
||||
* initial value is @a init. The values are processed in order.
|
||||
*
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @param __init Starting value to add other values to.
|
||||
* @return The final sum.
|
||||
*/
|
||||
template<typename _InputIterator, typename _Tp>
|
||||
inline _Tp
|
||||
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
for (; __first != __last; ++__first)
|
||||
__init = __init + *__first;
|
||||
return __init;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accumulate values in a range with operation.
|
||||
*
|
||||
* Accumulates the values in the range [first,last) using the function
|
||||
* object @p __binary_op. The initial value is @p __init. The values are
|
||||
* processed in order.
|
||||
*
|
||||
* @param __first Start of range.
|
||||
* @param __last End of range.
|
||||
* @param __init Starting value to add other values to.
|
||||
* @param __binary_op Function object to accumulate with.
|
||||
* @return The final sum.
|
||||
*/
|
||||
template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
|
||||
inline _Tp
|
||||
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
|
||||
_BinaryOperation __binary_op)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
for (; __first != __last; ++__first)
|
||||
__init = __binary_op(__init, *__first);
|
||||
return __init;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute inner product of two ranges.
|
||||
*
|
||||
* Starting with an initial value of @p __init, multiplies successive
|
||||
* elements from the two ranges and adds each product into the accumulated
|
||||
* value using operator+(). The values in the ranges are processed in
|
||||
* order.
|
||||
*
|
||||
* @param __first1 Start of range 1.
|
||||
* @param __last1 End of range 1.
|
||||
* @param __first2 Start of range 2.
|
||||
* @param __init Starting value to add other values to.
|
||||
* @return The final inner product.
|
||||
*/
|
||||
template<typename _InputIterator1, typename _InputIterator2, typename _Tp>
|
||||
inline _Tp
|
||||
inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
|
||||
_InputIterator2 __first2, _Tp __init)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
|
||||
for (; __first1 != __last1; ++__first1, (void)++__first2)
|
||||
__init = __init + (*__first1 * *__first2);
|
||||
return __init;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute inner product of two ranges.
|
||||
*
|
||||
* Starting with an initial value of @p __init, applies @p __binary_op2 to
|
||||
* successive elements from the two ranges and accumulates each result into
|
||||
* the accumulated value using @p __binary_op1. The values in the ranges are
|
||||
* processed in order.
|
||||
*
|
||||
* @param __first1 Start of range 1.
|
||||
* @param __last1 End of range 1.
|
||||
* @param __first2 Start of range 2.
|
||||
* @param __init Starting value to add other values to.
|
||||
* @param __binary_op1 Function object to accumulate with.
|
||||
* @param __binary_op2 Function object to apply to pairs of input values.
|
||||
* @return The final inner product.
|
||||
*/
|
||||
template<typename _InputIterator1, typename _InputIterator2, typename _Tp,
|
||||
typename _BinaryOperation1, typename _BinaryOperation2>
|
||||
inline _Tp
|
||||
inner_product(_InputIterator1 __first1, _InputIterator1 __last1,
|
||||
_InputIterator2 __first2, _Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2)
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
|
||||
__glibcxx_requires_valid_range(__first1, __last1);
|
||||
|
||||
for (; __first1 != __last1; ++__first1, (void)++__first2)
|
||||
__init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
|
||||
return __init;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return list of partial sums
|
||||
*
|
||||
* Accumulates the values in the range [first,last) using the @c + operator.
|
||||
* As each successive input value is added into the total, that partial sum
|
||||
* is written to @p __result. Therefore, the first value in @p __result is
|
||||
* the first value of the input, the second value in @p __result is the sum
|
||||
* of the first and second input values, and so on.
|
||||
*
|
||||
* @param __first Start of input range.
|
||||
* @param __last End of input range.
|
||||
* @param __result Output sum.
|
||||
* @return Iterator pointing just beyond the values written to __result.
|
||||
*/
|
||||
template<typename _InputIterator, typename _OutputIterator>
|
||||
_OutputIterator
|
||||
partial_sum(_InputIterator __first, _InputIterator __last,
|
||||
_OutputIterator __result)
|
||||
{
|
||||
typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
|
||||
_ValueType>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
if (__first == __last)
|
||||
return __result;
|
||||
_ValueType __value = *__first;
|
||||
*__result = __value;
|
||||
while (++__first != __last)
|
||||
{
|
||||
__value = __value + *__first;
|
||||
*++__result = __value;
|
||||
}
|
||||
return ++__result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return list of partial sums
|
||||
*
|
||||
* Accumulates the values in the range [first,last) using @p __binary_op.
|
||||
* As each successive input value is added into the total, that partial sum
|
||||
* is written to @p __result. Therefore, the first value in @p __result is
|
||||
* the first value of the input, the second value in @p __result is the sum
|
||||
* of the first and second input values, and so on.
|
||||
*
|
||||
* @param __first Start of input range.
|
||||
* @param __last End of input range.
|
||||
* @param __result Output sum.
|
||||
* @param __binary_op Function object.
|
||||
* @return Iterator pointing just beyond the values written to __result.
|
||||
*/
|
||||
template<typename _InputIterator, typename _OutputIterator,
|
||||
typename _BinaryOperation>
|
||||
_OutputIterator
|
||||
partial_sum(_InputIterator __first, _InputIterator __last,
|
||||
_OutputIterator __result, _BinaryOperation __binary_op)
|
||||
{
|
||||
typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
|
||||
_ValueType>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
if (__first == __last)
|
||||
return __result;
|
||||
_ValueType __value = *__first;
|
||||
*__result = __value;
|
||||
while (++__first != __last)
|
||||
{
|
||||
__value = __binary_op(__value, *__first);
|
||||
*++__result = __value;
|
||||
}
|
||||
return ++__result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return differences between adjacent values.
|
||||
*
|
||||
* Computes the difference between adjacent values in the range
|
||||
* [first,last) using operator-() and writes the result to @p __result.
|
||||
*
|
||||
* @param __first Start of input range.
|
||||
* @param __last End of input range.
|
||||
* @param __result Output sums.
|
||||
* @return Iterator pointing just beyond the values written to result.
|
||||
*
|
||||
* _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
* DR 539. partial_sum and adjacent_difference should mention requirements
|
||||
*/
|
||||
template<typename _InputIterator, typename _OutputIterator>
|
||||
_OutputIterator
|
||||
adjacent_difference(_InputIterator __first,
|
||||
_InputIterator __last, _OutputIterator __result)
|
||||
{
|
||||
typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
|
||||
_ValueType>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
if (__first == __last)
|
||||
return __result;
|
||||
_ValueType __value = *__first;
|
||||
*__result = __value;
|
||||
while (++__first != __last)
|
||||
{
|
||||
_ValueType __tmp = *__first;
|
||||
*++__result = __tmp - __value;
|
||||
__value = _GLIBCXX_MOVE(__tmp);
|
||||
}
|
||||
return ++__result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return differences between adjacent values.
|
||||
*
|
||||
* Computes the difference between adjacent values in the range
|
||||
* [__first,__last) using the function object @p __binary_op and writes the
|
||||
* result to @p __result.
|
||||
*
|
||||
* @param __first Start of input range.
|
||||
* @param __last End of input range.
|
||||
* @param __result Output sum.
|
||||
* @param __binary_op Function object.
|
||||
* @return Iterator pointing just beyond the values written to result.
|
||||
*
|
||||
* _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
* DR 539. partial_sum and adjacent_difference should mention requirements
|
||||
*/
|
||||
template<typename _InputIterator, typename _OutputIterator,
|
||||
typename _BinaryOperation>
|
||||
_OutputIterator
|
||||
adjacent_difference(_InputIterator __first, _InputIterator __last,
|
||||
_OutputIterator __result, _BinaryOperation __binary_op)
|
||||
{
|
||||
typedef typename iterator_traits<_InputIterator>::value_type _ValueType;
|
||||
|
||||
// concept requirements
|
||||
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
|
||||
__glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
|
||||
_ValueType>)
|
||||
__glibcxx_requires_valid_range(__first, __last);
|
||||
|
||||
if (__first == __last)
|
||||
return __result;
|
||||
_ValueType __value = *__first;
|
||||
*__result = __value;
|
||||
while (++__first != __last)
|
||||
{
|
||||
_ValueType __tmp = *__first;
|
||||
*++__result = __binary_op(__tmp, __value);
|
||||
__value = _GLIBCXX_MOVE(__tmp);
|
||||
}
|
||||
return ++__result;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_ALGO
|
||||
} // namespace std
|
||||
|
||||
#endif /* _STL_NUMERIC_H */
|
||||
|
|
@ -0,0 +1,543 @@
|
|||
// Pair implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_pair.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{utility}
|
||||
*/
|
||||
|
||||
#ifndef _STL_PAIR_H
|
||||
#define _STL_PAIR_H 1
|
||||
|
||||
#include "../bits/move.h" // for std::move / std::forward, and std::swap
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../type_traits" // for std::__decay_and_strip too
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/// piecewise_construct_t
|
||||
struct piecewise_construct_t { explicit piecewise_construct_t() = default; };
|
||||
|
||||
/// piecewise_construct
|
||||
_GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct =
|
||||
piecewise_construct_t();
|
||||
|
||||
// Forward declarations.
|
||||
template<typename...>
|
||||
class tuple;
|
||||
|
||||
template<std::size_t...>
|
||||
struct _Index_tuple;
|
||||
|
||||
// Concept utility functions, reused in conditionally-explicit
|
||||
// constructors.
|
||||
// See PR 70437, don't look at is_constructible or
|
||||
// is_convertible if the types are the same to
|
||||
// avoid querying those properties for incomplete types.
|
||||
template <bool, typename _T1, typename _T2>
|
||||
struct _PCC
|
||||
{
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ConstructiblePair()
|
||||
{
|
||||
return __and_<is_constructible<_T1, const _U1&>,
|
||||
is_constructible<_T2, const _U2&>>::value;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ImplicitlyConvertiblePair()
|
||||
{
|
||||
return __and_<is_convertible<const _U1&, _T1>,
|
||||
is_convertible<const _U2&, _T2>>::value;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _MoveConstructiblePair()
|
||||
{
|
||||
return __and_<is_constructible<_T1, _U1&&>,
|
||||
is_constructible<_T2, _U2&&>>::value;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ImplicitlyMoveConvertiblePair()
|
||||
{
|
||||
return __and_<is_convertible<_U1&&, _T1>,
|
||||
is_convertible<_U2&&, _T2>>::value;
|
||||
}
|
||||
|
||||
template <bool __implicit, typename _U1, typename _U2>
|
||||
static constexpr bool _CopyMovePair()
|
||||
{
|
||||
using __do_converts = __and_<is_convertible<const _U1&, _T1>,
|
||||
is_convertible<_U2&&, _T2>>;
|
||||
using __converts = typename conditional<__implicit,
|
||||
__do_converts,
|
||||
__not_<__do_converts>>::type;
|
||||
return __and_<is_constructible<_T1, const _U1&>,
|
||||
is_constructible<_T2, _U2&&>,
|
||||
__converts
|
||||
>::value;
|
||||
}
|
||||
|
||||
template <bool __implicit, typename _U1, typename _U2>
|
||||
static constexpr bool _MoveCopyPair()
|
||||
{
|
||||
using __do_converts = __and_<is_convertible<_U1&&, _T1>,
|
||||
is_convertible<const _U2&, _T2>>;
|
||||
using __converts = typename conditional<__implicit,
|
||||
__do_converts,
|
||||
__not_<__do_converts>>::type;
|
||||
return __and_<is_constructible<_T1, _U1&&>,
|
||||
is_constructible<_T2, const _U2&&>,
|
||||
__converts
|
||||
>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _T1, typename _T2>
|
||||
struct _PCC<false, _T1, _T2>
|
||||
{
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ConstructiblePair()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ImplicitlyConvertiblePair()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _MoveConstructiblePair()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename _U1, typename _U2>
|
||||
static constexpr bool _ImplicitlyMoveConvertiblePair()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// PR libstdc++/79141, a utility type for preventing
|
||||
// initialization of an argument of a disabled assignment
|
||||
// operator from a pair of empty braces.
|
||||
struct __nonesuch_no_braces : std::__nonesuch {
|
||||
explicit __nonesuch_no_braces(const __nonesuch&) = delete;
|
||||
};
|
||||
#endif // C++11
|
||||
|
||||
template<typename _U1, typename _U2> class __pair_base
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _T1, typename _T2> friend struct pair;
|
||||
__pair_base() = default;
|
||||
~__pair_base() = default;
|
||||
__pair_base(const __pair_base&) = default;
|
||||
__pair_base& operator=(const __pair_base&) = delete;
|
||||
#endif // C++11
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Struct holding two objects of arbitrary type.
|
||||
*
|
||||
* @tparam _T1 Type of first object.
|
||||
* @tparam _T2 Type of second object.
|
||||
*/
|
||||
template<typename _T1, typename _T2>
|
||||
struct pair
|
||||
: private __pair_base<_T1, _T2>
|
||||
{
|
||||
typedef _T1 first_type; /// @c first_type is the first bound type
|
||||
typedef _T2 second_type; /// @c second_type is the second bound type
|
||||
|
||||
_T1 first; /// @c first is a copy of the first object
|
||||
_T2 second; /// @c second is a copy of the second object
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 265. std::pair::pair() effects overly restrictive
|
||||
/** The default constructor creates @c first and @c second using their
|
||||
* respective default constructors. */
|
||||
#if __cplusplus >= 201103L
|
||||
template <typename _U1 = _T1,
|
||||
typename _U2 = _T2,
|
||||
typename enable_if<__and_<
|
||||
__is_implicitly_default_constructible<_U1>,
|
||||
__is_implicitly_default_constructible<_U2>>
|
||||
::value, bool>::type = true>
|
||||
#endif
|
||||
_GLIBCXX_CONSTEXPR pair()
|
||||
: first(), second() { }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template <typename _U1 = _T1,
|
||||
typename _U2 = _T2,
|
||||
typename enable_if<__and_<
|
||||
is_default_constructible<_U1>,
|
||||
is_default_constructible<_U2>,
|
||||
__not_<
|
||||
__and_<__is_implicitly_default_constructible<_U1>,
|
||||
__is_implicitly_default_constructible<_U2>>>>
|
||||
::value, bool>::type = false>
|
||||
explicit constexpr pair()
|
||||
: first(), second() { }
|
||||
#endif
|
||||
|
||||
/** Two objects may be passed to a @c pair constructor to be copied. */
|
||||
#if __cplusplus < 201103L
|
||||
pair(const _T1& __a, const _T2& __b)
|
||||
: first(__a), second(__b) { }
|
||||
#else
|
||||
// Shortcut for constraining the templates that don't take pairs.
|
||||
using _PCCP = _PCC<true, _T1, _T2>;
|
||||
|
||||
template<typename _U1 = _T1, typename _U2=_T2, typename
|
||||
enable_if<_PCCP::template
|
||||
_ConstructiblePair<_U1, _U2>()
|
||||
&& _PCCP::template
|
||||
_ImplicitlyConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(const _T1& __a, const _T2& __b)
|
||||
: first(__a), second(__b) { }
|
||||
|
||||
template<typename _U1 = _T1, typename _U2=_T2, typename
|
||||
enable_if<_PCCP::template
|
||||
_ConstructiblePair<_U1, _U2>()
|
||||
&& !_PCCP::template
|
||||
_ImplicitlyConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr pair(const _T1& __a, const _T2& __b)
|
||||
: first(__a), second(__b) { }
|
||||
#endif
|
||||
|
||||
/** There is also a templated copy ctor for the @c pair class itself. */
|
||||
#if __cplusplus < 201103L
|
||||
template<typename _U1, typename _U2>
|
||||
pair(const pair<_U1, _U2>& __p)
|
||||
: first(__p.first), second(__p.second) { }
|
||||
#else
|
||||
// Shortcut for constraining the templates that take pairs.
|
||||
template <typename _U1, typename _U2>
|
||||
using _PCCFP = _PCC<!is_same<_T1, _U1>::value
|
||||
|| !is_same<_T2, _U2>::value,
|
||||
_T1, _T2>;
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCFP<_U1, _U2>::template
|
||||
_ConstructiblePair<_U1, _U2>()
|
||||
&& _PCCFP<_U1, _U2>::template
|
||||
_ImplicitlyConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(const pair<_U1, _U2>& __p)
|
||||
: first(__p.first), second(__p.second) { }
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCFP<_U1, _U2>::template
|
||||
_ConstructiblePair<_U1, _U2>()
|
||||
&& !_PCCFP<_U1, _U2>::template
|
||||
_ImplicitlyConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr pair(const pair<_U1, _U2>& __p)
|
||||
: first(__p.first), second(__p.second) { }
|
||||
|
||||
constexpr pair(const pair&) = default;
|
||||
constexpr pair(pair&&) = default;
|
||||
|
||||
// DR 811.
|
||||
template<typename _U1, typename
|
||||
enable_if<_PCCP::template
|
||||
_MoveCopyPair<true, _U1, _T2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(_U1&& __x, const _T2& __y)
|
||||
: first(std::forward<_U1>(__x)), second(__y) { }
|
||||
|
||||
template<typename _U1, typename
|
||||
enable_if<_PCCP::template
|
||||
_MoveCopyPair<false, _U1, _T2>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr pair(_U1&& __x, const _T2& __y)
|
||||
: first(std::forward<_U1>(__x)), second(__y) { }
|
||||
|
||||
template<typename _U2, typename
|
||||
enable_if<_PCCP::template
|
||||
_CopyMovePair<true, _T1, _U2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(const _T1& __x, _U2&& __y)
|
||||
: first(__x), second(std::forward<_U2>(__y)) { }
|
||||
|
||||
template<typename _U2, typename
|
||||
enable_if<_PCCP::template
|
||||
_CopyMovePair<false, _T1, _U2>(),
|
||||
bool>::type=false>
|
||||
explicit pair(const _T1& __x, _U2&& __y)
|
||||
: first(__x), second(std::forward<_U2>(__y)) { }
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCP::template
|
||||
_MoveConstructiblePair<_U1, _U2>()
|
||||
&& _PCCP::template
|
||||
_ImplicitlyMoveConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(_U1&& __x, _U2&& __y)
|
||||
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCP::template
|
||||
_MoveConstructiblePair<_U1, _U2>()
|
||||
&& !_PCCP::template
|
||||
_ImplicitlyMoveConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr pair(_U1&& __x, _U2&& __y)
|
||||
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
|
||||
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCFP<_U1, _U2>::template
|
||||
_MoveConstructiblePair<_U1, _U2>()
|
||||
&& _PCCFP<_U1, _U2>::template
|
||||
_ImplicitlyMoveConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=true>
|
||||
constexpr pair(pair<_U1, _U2>&& __p)
|
||||
: first(std::forward<_U1>(__p.first)),
|
||||
second(std::forward<_U2>(__p.second)) { }
|
||||
|
||||
template<typename _U1, typename _U2, typename
|
||||
enable_if<_PCCFP<_U1, _U2>::template
|
||||
_MoveConstructiblePair<_U1, _U2>()
|
||||
&& !_PCCFP<_U1, _U2>::template
|
||||
_ImplicitlyMoveConvertiblePair<_U1, _U2>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr pair(pair<_U1, _U2>&& __p)
|
||||
: first(std::forward<_U1>(__p.first)),
|
||||
second(std::forward<_U2>(__p.second)) { }
|
||||
|
||||
template<typename... _Args1, typename... _Args2>
|
||||
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
|
||||
|
||||
pair&
|
||||
operator=(typename conditional<
|
||||
__and_<is_copy_assignable<_T1>,
|
||||
is_copy_assignable<_T2>>::value,
|
||||
const pair&, const __nonesuch_no_braces&>::type __p)
|
||||
{
|
||||
first = __p.first;
|
||||
second = __p.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
pair&
|
||||
operator=(typename conditional<
|
||||
__and_<is_move_assignable<_T1>,
|
||||
is_move_assignable<_T2>>::value,
|
||||
pair&&, __nonesuch_no_braces&&>::type __p)
|
||||
noexcept(__and_<is_nothrow_move_assignable<_T1>,
|
||||
is_nothrow_move_assignable<_T2>>::value)
|
||||
{
|
||||
first = std::forward<first_type>(__p.first);
|
||||
second = std::forward<second_type>(__p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _U1, typename _U2>
|
||||
typename enable_if<__and_<is_assignable<_T1&, const _U1&>,
|
||||
is_assignable<_T2&, const _U2&>>::value,
|
||||
pair&>::type
|
||||
operator=(const pair<_U1, _U2>& __p)
|
||||
{
|
||||
first = __p.first;
|
||||
second = __p.second;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _U1, typename _U2>
|
||||
typename enable_if<__and_<is_assignable<_T1&, _U1&&>,
|
||||
is_assignable<_T2&, _U2&&>>::value,
|
||||
pair&>::type
|
||||
operator=(pair<_U1, _U2>&& __p)
|
||||
{
|
||||
first = std::forward<_U1>(__p.first);
|
||||
second = std::forward<_U2>(__p.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
swap(pair& __p)
|
||||
noexcept(__and_<__is_nothrow_swappable<_T1>,
|
||||
__is_nothrow_swappable<_T2>>::value)
|
||||
{
|
||||
using std::swap;
|
||||
swap(first, __p.first);
|
||||
swap(second, __p.second);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename... _Args1, std::size_t... _Indexes1,
|
||||
typename... _Args2, std::size_t... _Indexes2>
|
||||
pair(tuple<_Args1...>&, tuple<_Args2...>&,
|
||||
_Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>);
|
||||
#endif
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>;
|
||||
#endif
|
||||
|
||||
/// Two pairs of the same type are equal iff their members are equal.
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return __x.first == __y.first && __x.second == __y.second; }
|
||||
|
||||
/// <http://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html>
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return __x.first < __y.first
|
||||
|| (!(__y.first < __x.first) && __x.second < __y.second); }
|
||||
|
||||
/// Uses @c operator== to find the result.
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return !(__x == __y); }
|
||||
|
||||
/// Uses @c operator< to find the result.
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return __y < __x; }
|
||||
|
||||
/// Uses @c operator< to find the result.
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return !(__y < __x); }
|
||||
|
||||
/// Uses @c operator< to find the result.
|
||||
template<typename _T1, typename _T2>
|
||||
inline _GLIBCXX_CONSTEXPR bool
|
||||
operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y)
|
||||
{ return !(__x < __y); }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/// See std::pair::swap().
|
||||
// Note: no std::swap overloads in C++03 mode, this has performance
|
||||
// implications, see, eg, libstdc++/38466.
|
||||
template<typename _T1, typename _T2>
|
||||
inline
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
// Constrained free swap overload, see p0185r1
|
||||
typename enable_if<__and_<__is_swappable<_T1>,
|
||||
__is_swappable<_T2>>::value>::type
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
|
||||
noexcept(noexcept(__x.swap(__y)))
|
||||
{ __x.swap(__y); }
|
||||
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
template<typename _T1, typename _T2>
|
||||
typename enable_if<!__and_<__is_swappable<_T1>,
|
||||
__is_swappable<_T2>>::value>::type
|
||||
swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
|
||||
#endif
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
/**
|
||||
* @brief A convenience wrapper for creating a pair from two objects.
|
||||
* @param __x The first object.
|
||||
* @param __y The second object.
|
||||
* @return A newly-constructed pair<> object of the appropriate type.
|
||||
*
|
||||
* The standard requires that the objects be passed by reference-to-const,
|
||||
* but LWG issue #181 says they should be passed by const value. We follow
|
||||
* the LWG by default.
|
||||
*/
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 181. make_pair() unintended behavior
|
||||
#if __cplusplus >= 201103L
|
||||
// NB: DR 706.
|
||||
template<typename _T1, typename _T2>
|
||||
constexpr pair<typename __decay_and_strip<_T1>::__type,
|
||||
typename __decay_and_strip<_T2>::__type>
|
||||
make_pair(_T1&& __x, _T2&& __y)
|
||||
{
|
||||
typedef typename __decay_and_strip<_T1>::__type __ds_type1;
|
||||
typedef typename __decay_and_strip<_T2>::__type __ds_type2;
|
||||
typedef pair<__ds_type1, __ds_type2> __pair_type;
|
||||
return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y));
|
||||
}
|
||||
#else
|
||||
template<typename _T1, typename _T2>
|
||||
inline pair<_T1, _T2>
|
||||
make_pair(_T1 __x, _T2 __y)
|
||||
{ return pair<_T1, _T2>(__x, __y); }
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif /* _STL_PAIR_H */
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// std::rel_ops implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the, 2009 Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file bits/stl_relops.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{utility}
|
||||
*
|
||||
* Inclusion of this file has been removed from
|
||||
* all of the other STL headers for safety reasons, except std_utility.h.
|
||||
* For more information, see the thread of about twenty messages starting
|
||||
* with http://gcc.gnu.org/ml/libstdc++/2001-01/msg00223.html, or
|
||||
* http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.ambiguous_overloads
|
||||
*
|
||||
* Short summary: the rel_ops operators should be avoided for the present.
|
||||
*/
|
||||
|
||||
#ifndef _STL_RELOPS_H
|
||||
#define _STL_RELOPS_H 1
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace rel_ops
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/** @namespace std::rel_ops
|
||||
* @brief The generated relational operators are sequestered here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Defines @c != for arbitrary types, in terms of @c ==.
|
||||
* @param __x A thing.
|
||||
* @param __y Another thing.
|
||||
* @return __x != __y
|
||||
*
|
||||
* This function uses @c == to determine its result.
|
||||
*/
|
||||
template <class _Tp>
|
||||
inline bool
|
||||
operator!=(const _Tp& __x, const _Tp& __y)
|
||||
{ return !(__x == __y); }
|
||||
|
||||
/**
|
||||
* @brief Defines @c > for arbitrary types, in terms of @c <.
|
||||
* @param __x A thing.
|
||||
* @param __y Another thing.
|
||||
* @return __x > __y
|
||||
*
|
||||
* This function uses @c < to determine its result.
|
||||
*/
|
||||
template <class _Tp>
|
||||
inline bool
|
||||
operator>(const _Tp& __x, const _Tp& __y)
|
||||
{ return __y < __x; }
|
||||
|
||||
/**
|
||||
* @brief Defines @c <= for arbitrary types, in terms of @c <.
|
||||
* @param __x A thing.
|
||||
* @param __y Another thing.
|
||||
* @return __x <= __y
|
||||
*
|
||||
* This function uses @c < to determine its result.
|
||||
*/
|
||||
template <class _Tp>
|
||||
inline bool
|
||||
operator<=(const _Tp& __x, const _Tp& __y)
|
||||
{ return !(__y < __x); }
|
||||
|
||||
/**
|
||||
* @brief Defines @c >= for arbitrary types, in terms of @c <.
|
||||
* @param __x A thing.
|
||||
* @param __y Another thing.
|
||||
* @return __x >= __y
|
||||
*
|
||||
* This function uses @c < to determine its result.
|
||||
*/
|
||||
template <class _Tp>
|
||||
inline bool
|
||||
operator>=(const _Tp& __x, const _Tp& __y)
|
||||
{ return !(__x < __y); }
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace rel_ops
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif /* _STL_RELOPS_H */
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
// Temporary buffer implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_tempbuf.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _STL_TEMPBUF_H
|
||||
#define _STL_TEMPBUF_H 1
|
||||
|
||||
#include "../bits/stl_algobase.h"
|
||||
#include "../bits/stl_construct.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Allocates a temporary buffer.
|
||||
* @param __len The number of objects of type Tp.
|
||||
* @return See full description.
|
||||
*
|
||||
* Reinventing the wheel, but this time with prettier spokes!
|
||||
*
|
||||
* This function tries to obtain storage for @c __len adjacent Tp
|
||||
* objects. The objects themselves are not constructed, of course.
|
||||
* A pair<> is returned containing <em>the buffer s address and
|
||||
* capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
|
||||
* no storage can be obtained.</em> Note that the capacity obtained
|
||||
* may be less than that requested if the memory is unavailable;
|
||||
* you should compare len with the .second return value.
|
||||
*
|
||||
* Provides the nothrow exception guarantee.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
pair<_Tp*, ptrdiff_t>
|
||||
get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
|
||||
{
|
||||
const ptrdiff_t __max =
|
||||
__gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
|
||||
if (__len > __max)
|
||||
__len = __max;
|
||||
|
||||
while (__len > 0)
|
||||
{
|
||||
_Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
|
||||
std::nothrow));
|
||||
if (__tmp != 0)
|
||||
return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
|
||||
__len /= 2;
|
||||
}
|
||||
return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The companion to get_temporary_buffer().
|
||||
* @param __p A buffer previously allocated by get_temporary_buffer.
|
||||
* @return None.
|
||||
*
|
||||
* Frees the memory pointed to by __p.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline void
|
||||
return_temporary_buffer(_Tp* __p)
|
||||
{ ::operator delete(__p, std::nothrow); }
|
||||
|
||||
|
||||
/**
|
||||
* This class is used in two places: stl_algo.h and ext/memory,
|
||||
* where it is wrapped as the temporary_buffer class. See
|
||||
* temporary_buffer docs for more notes.
|
||||
*/
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
class _Temporary_buffer
|
||||
{
|
||||
// concept requirements
|
||||
__glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
|
||||
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef pointer iterator;
|
||||
typedef ptrdiff_t size_type;
|
||||
|
||||
protected:
|
||||
size_type _M_original_len;
|
||||
size_type _M_len;
|
||||
pointer _M_buffer;
|
||||
|
||||
public:
|
||||
/// As per Table mumble.
|
||||
size_type
|
||||
size() const
|
||||
{ return _M_len; }
|
||||
|
||||
/// Returns the size requested by the constructor; may be >size().
|
||||
size_type
|
||||
requested_size() const
|
||||
{ return _M_original_len; }
|
||||
|
||||
/// As per Table mumble.
|
||||
iterator
|
||||
begin()
|
||||
{ return _M_buffer; }
|
||||
|
||||
/// As per Table mumble.
|
||||
iterator
|
||||
end()
|
||||
{ return _M_buffer + _M_len; }
|
||||
|
||||
/**
|
||||
* Constructs a temporary buffer of a size somewhere between
|
||||
* zero and the size of the given range.
|
||||
*/
|
||||
_Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last);
|
||||
|
||||
~_Temporary_buffer()
|
||||
{
|
||||
std::_Destroy(_M_buffer, _M_buffer + _M_len);
|
||||
std::return_temporary_buffer(_M_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
// Disable copy constructor and assignment operator.
|
||||
_Temporary_buffer(const _Temporary_buffer&);
|
||||
|
||||
void
|
||||
operator=(const _Temporary_buffer&);
|
||||
};
|
||||
|
||||
|
||||
template<bool>
|
||||
struct __uninitialized_construct_buf_dispatch
|
||||
{
|
||||
template<typename _Pointer, typename _ForwardIterator>
|
||||
static void
|
||||
__ucr(_Pointer __first, _Pointer __last,
|
||||
_ForwardIterator __seed)
|
||||
{
|
||||
if(__first == __last)
|
||||
return;
|
||||
|
||||
_Pointer __cur = __first;
|
||||
#ifdef AH_USE_EXCEPTIONS
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
std::_Construct(std::__addressof(*__first),
|
||||
_GLIBCXX_MOVE(*__seed));
|
||||
_Pointer __prev = __cur;
|
||||
++__cur;
|
||||
for(; __cur != __last; ++__cur, ++__prev)
|
||||
std::_Construct(std::__addressof(*__cur),
|
||||
_GLIBCXX_MOVE(*__prev));
|
||||
*__seed = _GLIBCXX_MOVE(*__prev);
|
||||
}
|
||||
#ifdef AH_USE_EXCEPTIONS
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_construct_buf_dispatch<true>
|
||||
{
|
||||
template<typename _Pointer, typename _ForwardIterator>
|
||||
static void
|
||||
__ucr(_Pointer, _Pointer, _ForwardIterator) { }
|
||||
};
|
||||
|
||||
// Constructs objects in the range [first, last).
|
||||
// Note that while these new objects will take valid values,
|
||||
// their exact value is not defined. In particular they may
|
||||
// be 'moved from'.
|
||||
//
|
||||
// While *__seed may be altered during this algorithm, it will have
|
||||
// the same value when the algorithm finishes, unless one of the
|
||||
// constructions throws.
|
||||
//
|
||||
// Requirements: _Pointer::value_type(_Tp&&) is valid.
|
||||
template<typename _Pointer, typename _ForwardIterator>
|
||||
inline void
|
||||
__uninitialized_construct_buf(_Pointer __first, _Pointer __last,
|
||||
_ForwardIterator __seed)
|
||||
{
|
||||
typedef typename std::iterator_traits<_Pointer>::value_type
|
||||
_ValueType;
|
||||
|
||||
std::__uninitialized_construct_buf_dispatch<
|
||||
__has_trivial_constructor(_ValueType)>::
|
||||
__ucr(__first, __last, __seed);
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
_Temporary_buffer<_ForwardIterator, _Tp>::
|
||||
_Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last)
|
||||
: _M_original_len(std::distance(__first, __last)),
|
||||
_M_len(0), _M_buffer(0)
|
||||
{
|
||||
#ifdef AH_USE_EXCEPTIONS
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
std::pair<pointer, size_type> __p(std::get_temporary_buffer<
|
||||
value_type>(_M_original_len));
|
||||
_M_buffer = __p.first;
|
||||
_M_len = __p.second;
|
||||
if (_M_buffer)
|
||||
std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len,
|
||||
__first);
|
||||
}
|
||||
#ifdef AH_USE_EXCEPTIONS
|
||||
__catch(...)
|
||||
{
|
||||
std::return_temporary_buffer(_M_buffer);
|
||||
_M_buffer = 0;
|
||||
_M_len = 0;
|
||||
__throw_exception_again;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _STL_TEMPBUF_H */
|
||||
|
|
@ -0,0 +1,885 @@
|
|||
// Raw memory manipulators -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/stl_uninitialized.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _STL_UNINITIALIZED_H
|
||||
#define _STL_UNINITIALIZED_H 1
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
#include "../utility"
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../type_traits"
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<bool _TrivialValueTypes>
|
||||
struct __uninitialized_copy
|
||||
{
|
||||
template<typename _InputIterator, typename _ForwardIterator>
|
||||
static _ForwardIterator
|
||||
__uninit_copy(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result)
|
||||
{
|
||||
_ForwardIterator __cur = __result;
|
||||
__try
|
||||
{
|
||||
for (; __first != __last; ++__first, (void)++__cur)
|
||||
std::_Construct(std::__addressof(*__cur), *__first);
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_copy<true>
|
||||
{
|
||||
template<typename _InputIterator, typename _ForwardIterator>
|
||||
static _ForwardIterator
|
||||
__uninit_copy(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result)
|
||||
{ return std::copy(__first, __last, __result); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copies the range [first,last) into result.
|
||||
* @param __first An input iterator.
|
||||
* @param __last An input iterator.
|
||||
* @param __result An output iterator.
|
||||
* @return __result + (__first - __last)
|
||||
*
|
||||
* Like copy(), but does not require an initialized output range.
|
||||
*/
|
||||
template<typename _InputIterator, typename _ForwardIterator>
|
||||
inline _ForwardIterator
|
||||
uninitialized_copy(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result)
|
||||
{
|
||||
typedef typename iterator_traits<_InputIterator>::value_type
|
||||
_ValueType1;
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType2;
|
||||
#if __cplusplus < 201103L
|
||||
const bool __assignable = true;
|
||||
#else
|
||||
// trivial types can have deleted assignment
|
||||
typedef typename iterator_traits<_InputIterator>::reference _RefType1;
|
||||
typedef typename iterator_traits<_ForwardIterator>::reference _RefType2;
|
||||
const bool __assignable = is_assignable<_RefType2, _RefType1>::value;
|
||||
#endif
|
||||
|
||||
return std::__uninitialized_copy<__is_trivial(_ValueType1)
|
||||
&& __is_trivial(_ValueType2)
|
||||
&& __assignable>::
|
||||
__uninit_copy(__first, __last, __result);
|
||||
}
|
||||
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_fill
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
static void
|
||||
__uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
|
||||
const _Tp& __x)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __cur != __last; ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur), __x);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_fill<true>
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
static void
|
||||
__uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
|
||||
const _Tp& __x)
|
||||
{ std::fill(__first, __last, __x); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Copies the value x into the range [first,last).
|
||||
* @param __first An input iterator.
|
||||
* @param __last An input iterator.
|
||||
* @param __x The source value.
|
||||
* @return Nothing.
|
||||
*
|
||||
* Like fill(), but does not require an initialized output range.
|
||||
*/
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
inline void
|
||||
uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
|
||||
const _Tp& __x)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
#if __cplusplus < 201103L
|
||||
const bool __assignable = true;
|
||||
#else
|
||||
// trivial types can have deleted assignment
|
||||
const bool __assignable = is_copy_assignable<_ValueType>::value;
|
||||
#endif
|
||||
|
||||
std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>::
|
||||
__uninit_fill(__first, __last, __x);
|
||||
}
|
||||
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_fill_n
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp>
|
||||
static _ForwardIterator
|
||||
__uninit_fill_n(_ForwardIterator __first, _Size __n,
|
||||
const _Tp& __x)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __n > 0; --__n, ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur), __x);
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_fill_n<true>
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp>
|
||||
static _ForwardIterator
|
||||
__uninit_fill_n(_ForwardIterator __first, _Size __n,
|
||||
const _Tp& __x)
|
||||
{ return std::fill_n(__first, __n, __x); }
|
||||
};
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// DR 1339. uninitialized_fill_n should return the end of its range
|
||||
/**
|
||||
* @brief Copies the value x into the range [first,first+n).
|
||||
* @param __first An input iterator.
|
||||
* @param __n The number of copies to make.
|
||||
* @param __x The source value.
|
||||
* @return Nothing.
|
||||
*
|
||||
* Like fill_n(), but does not require an initialized output range.
|
||||
*/
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp>
|
||||
inline _ForwardIterator
|
||||
uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
#if __cplusplus < 201103L
|
||||
const bool __assignable = true;
|
||||
#else
|
||||
// trivial types can have deleted assignment
|
||||
const bool __assignable = is_copy_assignable<_ValueType>::value;
|
||||
#endif
|
||||
return __uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>::
|
||||
__uninit_fill_n(__first, __n, __x);
|
||||
}
|
||||
|
||||
// Extensions: versions of uninitialized_copy, uninitialized_fill,
|
||||
// and uninitialized_fill_n that take an allocator parameter.
|
||||
// We dispatch back to the standard versions when we're given the
|
||||
// default allocator. For nondefault allocators we do not use
|
||||
// any of the POD optimizations.
|
||||
|
||||
template<typename _InputIterator, typename _ForwardIterator,
|
||||
typename _Allocator>
|
||||
_ForwardIterator
|
||||
__uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result, _Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __cur = __result;
|
||||
__try
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __first != __last; ++__first, (void)++__cur)
|
||||
__traits::construct(__alloc, std::__addressof(*__cur), *__first);
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __cur, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result, allocator<_Tp>&)
|
||||
{ return std::uninitialized_copy(__first, __last, __result); }
|
||||
|
||||
template<typename _InputIterator, typename _ForwardIterator,
|
||||
typename _Allocator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_move_a(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result, _Allocator& __alloc)
|
||||
{
|
||||
return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
|
||||
_GLIBCXX_MAKE_MOVE_ITERATOR(__last),
|
||||
__result, __alloc);
|
||||
}
|
||||
|
||||
template<typename _InputIterator, typename _ForwardIterator,
|
||||
typename _Allocator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_move_if_noexcept_a(_InputIterator __first,
|
||||
_InputIterator __last,
|
||||
_ForwardIterator __result,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
return std::__uninitialized_copy_a
|
||||
(_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
|
||||
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Tp, typename _Allocator>
|
||||
void
|
||||
__uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
|
||||
const _Tp& __x, _Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __cur != __last; ++__cur)
|
||||
__traits::construct(__alloc, std::__addressof(*__cur), __x);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Tp, typename _Tp2>
|
||||
inline void
|
||||
__uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
|
||||
const _Tp& __x, allocator<_Tp2>&)
|
||||
{ std::uninitialized_fill(__first, __last, __x); }
|
||||
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp,
|
||||
typename _Allocator>
|
||||
_ForwardIterator
|
||||
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
|
||||
const _Tp& __x, _Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __n > 0; --__n, ++__cur)
|
||||
__traits::construct(__alloc, std::__addressof(*__cur), __x);
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp,
|
||||
typename _Tp2>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
|
||||
const _Tp& __x, allocator<_Tp2>&)
|
||||
{ return std::uninitialized_fill_n(__first, __n, __x); }
|
||||
|
||||
|
||||
// Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
|
||||
// __uninitialized_fill_move, __uninitialized_move_fill.
|
||||
// All of these algorithms take a user-supplied allocator, which is used
|
||||
// for construction and destruction.
|
||||
|
||||
// __uninitialized_copy_move
|
||||
// Copies [first1, last1) into [result, result + (last1 - first1)), and
|
||||
// move [first2, last2) into
|
||||
// [result, result + (last1 - first1) + (last2 - first2)).
|
||||
template<typename _InputIterator1, typename _InputIterator2,
|
||||
typename _ForwardIterator, typename _Allocator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_copy_move(_InputIterator1 __first1,
|
||||
_InputIterator1 __last1,
|
||||
_InputIterator2 __first2,
|
||||
_InputIterator2 __last2,
|
||||
_ForwardIterator __result,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
|
||||
__result,
|
||||
__alloc);
|
||||
__try
|
||||
{
|
||||
return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __mid, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
// __uninitialized_move_copy
|
||||
// Moves [first1, last1) into [result, result + (last1 - first1)), and
|
||||
// copies [first2, last2) into
|
||||
// [result, result + (last1 - first1) + (last2 - first2)).
|
||||
template<typename _InputIterator1, typename _InputIterator2,
|
||||
typename _ForwardIterator, typename _Allocator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_move_copy(_InputIterator1 __first1,
|
||||
_InputIterator1 __last1,
|
||||
_InputIterator2 __first2,
|
||||
_InputIterator2 __last2,
|
||||
_ForwardIterator __result,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1,
|
||||
__result,
|
||||
__alloc);
|
||||
__try
|
||||
{
|
||||
return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __mid, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
// __uninitialized_fill_move
|
||||
// Fills [result, mid) with x, and moves [first, last) into
|
||||
// [mid, mid + (last - first)).
|
||||
template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
|
||||
typename _Allocator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid,
|
||||
const _Tp& __x, _InputIterator __first,
|
||||
_InputIterator __last, _Allocator& __alloc)
|
||||
{
|
||||
std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
|
||||
__try
|
||||
{
|
||||
return std::__uninitialized_move_a(__first, __last, __mid, __alloc);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __mid, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
// __uninitialized_move_fill
|
||||
// Moves [first1, last1) into [first2, first2 + (last1 - first1)), and
|
||||
// fills [first2 + (last1 - first1), last2) with x.
|
||||
template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
|
||||
typename _Allocator>
|
||||
inline void
|
||||
__uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1,
|
||||
_ForwardIterator __first2,
|
||||
_ForwardIterator __last2, const _Tp& __x,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1,
|
||||
__first2,
|
||||
__alloc);
|
||||
__try
|
||||
{
|
||||
std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first2, __mid2, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Extensions: __uninitialized_default, __uninitialized_default_n,
|
||||
// __uninitialized_default_a, __uninitialized_default_n_a.
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_default_1
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__uninit_default(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __cur != __last; ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur));
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_default_1<true>
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__uninit_default(_ForwardIterator __first, _ForwardIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
|
||||
std::fill(__first, __last, _ValueType());
|
||||
}
|
||||
};
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_default_n_1
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__uninit_default_n(_ForwardIterator __first, _Size __n)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __n > 0; --__n, ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur));
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_default_n_1<true>
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__uninit_default_n(_ForwardIterator __first, _Size __n)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
|
||||
return std::fill_n(__first, __n, _ValueType());
|
||||
}
|
||||
};
|
||||
|
||||
// __uninitialized_default
|
||||
// Fills [first, last) with std::distance(first, last) default
|
||||
// constructed value_types(s).
|
||||
template<typename _ForwardIterator>
|
||||
inline void
|
||||
__uninitialized_default(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
// trivial types can have deleted assignment
|
||||
const bool __assignable = is_copy_assignable<_ValueType>::value;
|
||||
|
||||
std::__uninitialized_default_1<__is_trivial(_ValueType)
|
||||
&& __assignable>::
|
||||
__uninit_default(__first, __last);
|
||||
}
|
||||
|
||||
// __uninitialized_default_n
|
||||
// Fills [first, first + n) with n default constructed value_type(s).
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_default_n(_ForwardIterator __first, _Size __n)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
// trivial types can have deleted assignment
|
||||
const bool __assignable = is_copy_assignable<_ValueType>::value;
|
||||
|
||||
return __uninitialized_default_n_1<__is_trivial(_ValueType)
|
||||
&& __assignable>::
|
||||
__uninit_default_n(__first, __n);
|
||||
}
|
||||
|
||||
|
||||
// __uninitialized_default_a
|
||||
// Fills [first, last) with std::distance(first, last) default
|
||||
// constructed value_types(s), constructed with the allocator alloc.
|
||||
template<typename _ForwardIterator, typename _Allocator>
|
||||
void
|
||||
__uninitialized_default_a(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __cur != __last; ++__cur)
|
||||
__traits::construct(__alloc, std::__addressof(*__cur));
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Tp>
|
||||
inline void
|
||||
__uninitialized_default_a(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
allocator<_Tp>&)
|
||||
{ std::__uninitialized_default(__first, __last); }
|
||||
|
||||
|
||||
// __uninitialized_default_n_a
|
||||
// Fills [first, first + n) with n default constructed value_types(s),
|
||||
// constructed with the allocator alloc.
|
||||
template<typename _ForwardIterator, typename _Size, typename _Allocator>
|
||||
_ForwardIterator
|
||||
__uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
|
||||
_Allocator& __alloc)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
|
||||
for (; __n > 0; --__n, ++__cur)
|
||||
__traits::construct(__alloc, std::__addressof(*__cur));
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur, __alloc);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _ForwardIterator, typename _Size, typename _Tp>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
|
||||
allocator<_Tp>&)
|
||||
{ return std::__uninitialized_default_n(__first, __n); }
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_default_novalue_1
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__uninit_default_novalue(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __cur != __last; ++__cur)
|
||||
std::_Construct_novalue(std::__addressof(*__cur));
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_default_novalue_1<true>
|
||||
{
|
||||
template<typename _ForwardIterator>
|
||||
static void
|
||||
__uninit_default_novalue(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<bool _TrivialValueType>
|
||||
struct __uninitialized_default_novalue_n_1
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
|
||||
{
|
||||
_ForwardIterator __cur = __first;
|
||||
__try
|
||||
{
|
||||
for (; __n > 0; --__n, ++__cur)
|
||||
std::_Construct_novalue(std::__addressof(*__cur));
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__first, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __uninitialized_default_novalue_n_1<true>
|
||||
{
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
static _ForwardIterator
|
||||
__uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
|
||||
{ return std::next(__first, __n); }
|
||||
};
|
||||
|
||||
// __uninitialized_default_novalue
|
||||
// Fills [first, last) with std::distance(first, last) default-initialized
|
||||
// value_types(s).
|
||||
template<typename _ForwardIterator>
|
||||
inline void
|
||||
__uninitialized_default_novalue(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
|
||||
std::__uninitialized_default_novalue_1<
|
||||
is_trivially_default_constructible<_ValueType>::value>::
|
||||
__uninit_default_novalue(__first, __last);
|
||||
}
|
||||
|
||||
// __uninitialized_default_n
|
||||
// Fills [first, first + n) with n default-initialized value_type(s).
|
||||
template<typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n)
|
||||
{
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type
|
||||
_ValueType;
|
||||
|
||||
return __uninitialized_default_novalue_n_1<
|
||||
is_trivially_default_constructible<_ValueType>::value>::
|
||||
__uninit_default_novalue_n(__first, __n);
|
||||
}
|
||||
|
||||
template<typename _InputIterator, typename _Size,
|
||||
typename _ForwardIterator>
|
||||
_ForwardIterator
|
||||
__uninitialized_copy_n(_InputIterator __first, _Size __n,
|
||||
_ForwardIterator __result, input_iterator_tag)
|
||||
{
|
||||
_ForwardIterator __cur = __result;
|
||||
__try
|
||||
{
|
||||
for (; __n > 0; --__n, ++__first, ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur), *__first);
|
||||
return __cur;
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Size,
|
||||
typename _ForwardIterator>
|
||||
inline _ForwardIterator
|
||||
__uninitialized_copy_n(_RandomAccessIterator __first, _Size __n,
|
||||
_ForwardIterator __result,
|
||||
random_access_iterator_tag)
|
||||
{ return std::uninitialized_copy(__first, __first + __n, __result); }
|
||||
|
||||
template<typename _InputIterator, typename _Size,
|
||||
typename _ForwardIterator>
|
||||
pair<_InputIterator, _ForwardIterator>
|
||||
__uninitialized_copy_n_pair(_InputIterator __first, _Size __n,
|
||||
_ForwardIterator __result, input_iterator_tag)
|
||||
{
|
||||
_ForwardIterator __cur = __result;
|
||||
__try
|
||||
{
|
||||
for (; __n > 0; --__n, ++__first, ++__cur)
|
||||
std::_Construct(std::__addressof(*__cur), *__first);
|
||||
return {__first, __cur};
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__result, __cur);
|
||||
__throw_exception_again;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _RandomAccessIterator, typename _Size,
|
||||
typename _ForwardIterator>
|
||||
inline pair<_RandomAccessIterator, _ForwardIterator>
|
||||
__uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n,
|
||||
_ForwardIterator __result,
|
||||
random_access_iterator_tag)
|
||||
{
|
||||
auto __second_res = uninitialized_copy(__first, __first + __n, __result);
|
||||
auto __first_res = std::next(__first, __n);
|
||||
return {__first_res, __second_res};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copies the range [first,first+n) into result.
|
||||
* @param __first An input iterator.
|
||||
* @param __n The number of elements to copy.
|
||||
* @param __result An output iterator.
|
||||
* @return __result + __n
|
||||
*
|
||||
* Like copy_n(), but does not require an initialized output range.
|
||||
*/
|
||||
template<typename _InputIterator, typename _Size, typename _ForwardIterator>
|
||||
inline _ForwardIterator
|
||||
uninitialized_copy_n(_InputIterator __first, _Size __n,
|
||||
_ForwardIterator __result)
|
||||
{ return std::__uninitialized_copy_n(__first, __n, __result,
|
||||
std::__iterator_category(__first)); }
|
||||
|
||||
template<typename _InputIterator, typename _Size, typename _ForwardIterator>
|
||||
inline pair<_InputIterator, _ForwardIterator>
|
||||
__uninitialized_copy_n_pair(_InputIterator __first, _Size __n,
|
||||
_ForwardIterator __result)
|
||||
{
|
||||
return
|
||||
std::__uninitialized_copy_n_pair(__first, __n, __result,
|
||||
std::__iterator_category(__first));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template <typename _ForwardIterator>
|
||||
inline void
|
||||
uninitialized_default_construct(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
__uninitialized_default_novalue(__first, __last);
|
||||
}
|
||||
|
||||
template <typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
uninitialized_default_construct_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
return __uninitialized_default_novalue_n(__first, __count);
|
||||
}
|
||||
|
||||
template <typename _ForwardIterator>
|
||||
inline void
|
||||
uninitialized_value_construct(_ForwardIterator __first,
|
||||
_ForwardIterator __last)
|
||||
{
|
||||
return __uninitialized_default(__first, __last);
|
||||
}
|
||||
|
||||
template <typename _ForwardIterator, typename _Size>
|
||||
inline _ForwardIterator
|
||||
uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
|
||||
{
|
||||
return __uninitialized_default_n(__first, __count);
|
||||
}
|
||||
|
||||
template <typename _InputIterator, typename _ForwardIterator>
|
||||
inline _ForwardIterator
|
||||
uninitialized_move(_InputIterator __first, _InputIterator __last,
|
||||
_ForwardIterator __result)
|
||||
{
|
||||
return std::uninitialized_copy
|
||||
(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
|
||||
_GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result);
|
||||
}
|
||||
|
||||
template <typename _InputIterator, typename _Size, typename _ForwardIterator>
|
||||
inline pair<_InputIterator, _ForwardIterator>
|
||||
uninitialized_move_n(_InputIterator __first, _Size __count,
|
||||
_ForwardIterator __result)
|
||||
{
|
||||
auto __res = std::__uninitialized_copy_n_pair
|
||||
(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
|
||||
__count, __result);
|
||||
return {__res.first.base(), __res.second};
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _STL_UNINITIALIZED_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,375 @@
|
|||
// Class template uniform_int_distribution -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2009-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* @file bits/uniform_int_dist.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{random}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H
|
||||
#define _GLIBCXX_BITS_UNIFORM_INT_DIST_H
|
||||
|
||||
#include "../type_traits"
|
||||
#include "../limits"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/* Determine whether number is a power of 2. */
|
||||
template<typename _Tp>
|
||||
inline bool
|
||||
_Power_of_2(_Tp __x)
|
||||
{
|
||||
return ((__x - 1) & __x) == 0;
|
||||
};
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Uniform discrete distribution for random numbers.
|
||||
* A discrete random distribution on the range @f$[min, max]@f$ with equal
|
||||
* probability throughout the range.
|
||||
*/
|
||||
template<typename _IntType = int>
|
||||
class uniform_int_distribution
|
||||
{
|
||||
static_assert(std::is_integral<_IntType>::value,
|
||||
"template argument must be an integral type");
|
||||
|
||||
public:
|
||||
/** The type of the range of the distribution. */
|
||||
typedef _IntType result_type;
|
||||
/** Parameter type. */
|
||||
struct param_type
|
||||
{
|
||||
typedef uniform_int_distribution<_IntType> distribution_type;
|
||||
|
||||
explicit
|
||||
param_type(_IntType __a = 0,
|
||||
_IntType __b = std::numeric_limits<_IntType>::max())
|
||||
: _M_a(__a), _M_b(__b)
|
||||
{
|
||||
__glibcxx_assert(_M_a <= _M_b);
|
||||
}
|
||||
|
||||
result_type
|
||||
a() const
|
||||
{ return _M_a; }
|
||||
|
||||
result_type
|
||||
b() const
|
||||
{ return _M_b; }
|
||||
|
||||
friend bool
|
||||
operator==(const param_type& __p1, const param_type& __p2)
|
||||
{ return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; }
|
||||
|
||||
friend bool
|
||||
operator!=(const param_type& __p1, const param_type& __p2)
|
||||
{ return !(__p1 == __p2); }
|
||||
|
||||
private:
|
||||
_IntType _M_a;
|
||||
_IntType _M_b;
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a uniform distribution object.
|
||||
*/
|
||||
explicit
|
||||
uniform_int_distribution(_IntType __a = 0,
|
||||
_IntType __b = std::numeric_limits<_IntType>::max())
|
||||
: _M_param(__a, __b)
|
||||
{ }
|
||||
|
||||
explicit
|
||||
uniform_int_distribution(const param_type& __p)
|
||||
: _M_param(__p)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief Resets the distribution state.
|
||||
*
|
||||
* Does nothing for the uniform integer distribution.
|
||||
*/
|
||||
void
|
||||
reset() { }
|
||||
|
||||
result_type
|
||||
a() const
|
||||
{ return _M_param.a(); }
|
||||
|
||||
result_type
|
||||
b() const
|
||||
{ return _M_param.b(); }
|
||||
|
||||
/**
|
||||
* @brief Returns the parameter set of the distribution.
|
||||
*/
|
||||
param_type
|
||||
param() const
|
||||
{ return _M_param; }
|
||||
|
||||
/**
|
||||
* @brief Sets the parameter set of the distribution.
|
||||
* @param __param The new parameter set of the distribution.
|
||||
*/
|
||||
void
|
||||
param(const param_type& __param)
|
||||
{ _M_param = __param; }
|
||||
|
||||
/**
|
||||
* @brief Returns the inclusive lower bound of the distribution range.
|
||||
*/
|
||||
result_type
|
||||
min() const
|
||||
{ return this->a(); }
|
||||
|
||||
/**
|
||||
* @brief Returns the inclusive upper bound of the distribution range.
|
||||
*/
|
||||
result_type
|
||||
max() const
|
||||
{ return this->b(); }
|
||||
|
||||
/**
|
||||
* @brief Generating functions.
|
||||
*/
|
||||
template<typename _UniformRandomNumberGenerator>
|
||||
result_type
|
||||
operator()(_UniformRandomNumberGenerator& __urng)
|
||||
{ return this->operator()(__urng, _M_param); }
|
||||
|
||||
template<typename _UniformRandomNumberGenerator>
|
||||
result_type
|
||||
operator()(_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __p);
|
||||
|
||||
template<typename _ForwardIterator,
|
||||
typename _UniformRandomNumberGenerator>
|
||||
void
|
||||
__generate(_ForwardIterator __f, _ForwardIterator __t,
|
||||
_UniformRandomNumberGenerator& __urng)
|
||||
{ this->__generate(__f, __t, __urng, _M_param); }
|
||||
|
||||
template<typename _ForwardIterator,
|
||||
typename _UniformRandomNumberGenerator>
|
||||
void
|
||||
__generate(_ForwardIterator __f, _ForwardIterator __t,
|
||||
_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __p)
|
||||
{ this->__generate_impl(__f, __t, __urng, __p); }
|
||||
|
||||
template<typename _UniformRandomNumberGenerator>
|
||||
void
|
||||
__generate(result_type* __f, result_type* __t,
|
||||
_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __p)
|
||||
{ this->__generate_impl(__f, __t, __urng, __p); }
|
||||
|
||||
/**
|
||||
* @brief Return true if two uniform integer distributions have
|
||||
* the same parameters.
|
||||
*/
|
||||
friend bool
|
||||
operator==(const uniform_int_distribution& __d1,
|
||||
const uniform_int_distribution& __d2)
|
||||
{ return __d1._M_param == __d2._M_param; }
|
||||
|
||||
private:
|
||||
template<typename _ForwardIterator,
|
||||
typename _UniformRandomNumberGenerator>
|
||||
void
|
||||
__generate_impl(_ForwardIterator __f, _ForwardIterator __t,
|
||||
_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __p);
|
||||
|
||||
param_type _M_param;
|
||||
};
|
||||
|
||||
template<typename _IntType>
|
||||
template<typename _UniformRandomNumberGenerator>
|
||||
typename uniform_int_distribution<_IntType>::result_type
|
||||
uniform_int_distribution<_IntType>::
|
||||
operator()(_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __param)
|
||||
{
|
||||
typedef typename _UniformRandomNumberGenerator::result_type
|
||||
_Gresult_type;
|
||||
typedef typename std::make_unsigned<result_type>::type __utype;
|
||||
typedef typename std::common_type<_Gresult_type, __utype>::type
|
||||
__uctype;
|
||||
|
||||
const __uctype __urngmin = __urng.min();
|
||||
const __uctype __urngmax = __urng.max();
|
||||
const __uctype __urngrange = __urngmax - __urngmin;
|
||||
const __uctype __urange
|
||||
= __uctype(__param.b()) - __uctype(__param.a());
|
||||
|
||||
__uctype __ret;
|
||||
|
||||
if (__urngrange > __urange)
|
||||
{
|
||||
// downscaling
|
||||
const __uctype __uerange = __urange + 1; // __urange can be zero
|
||||
const __uctype __scaling = __urngrange / __uerange;
|
||||
const __uctype __past = __uerange * __scaling;
|
||||
do
|
||||
__ret = __uctype(__urng()) - __urngmin;
|
||||
while (__ret >= __past);
|
||||
__ret /= __scaling;
|
||||
}
|
||||
else if (__urngrange < __urange)
|
||||
{
|
||||
// upscaling
|
||||
/*
|
||||
Note that every value in [0, urange]
|
||||
can be written uniquely as
|
||||
|
||||
(urngrange + 1) * high + low
|
||||
|
||||
where
|
||||
|
||||
high in [0, urange / (urngrange + 1)]
|
||||
|
||||
and
|
||||
|
||||
low in [0, urngrange].
|
||||
*/
|
||||
__uctype __tmp; // wraparound control
|
||||
do
|
||||
{
|
||||
const __uctype __uerngrange = __urngrange + 1;
|
||||
__tmp = (__uerngrange * operator()
|
||||
(__urng, param_type(0, __urange / __uerngrange)));
|
||||
__ret = __tmp + (__uctype(__urng()) - __urngmin);
|
||||
}
|
||||
while (__ret > __urange || __ret < __tmp);
|
||||
}
|
||||
else
|
||||
__ret = __uctype(__urng()) - __urngmin;
|
||||
|
||||
return __ret + __param.a();
|
||||
}
|
||||
|
||||
|
||||
template<typename _IntType>
|
||||
template<typename _ForwardIterator,
|
||||
typename _UniformRandomNumberGenerator>
|
||||
void
|
||||
uniform_int_distribution<_IntType>::
|
||||
__generate_impl(_ForwardIterator __f, _ForwardIterator __t,
|
||||
_UniformRandomNumberGenerator& __urng,
|
||||
const param_type& __param)
|
||||
{
|
||||
__glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
|
||||
typedef typename _UniformRandomNumberGenerator::result_type
|
||||
_Gresult_type;
|
||||
typedef typename std::make_unsigned<result_type>::type __utype;
|
||||
typedef typename std::common_type<_Gresult_type, __utype>::type
|
||||
__uctype;
|
||||
|
||||
const __uctype __urngmin = __urng.min();
|
||||
const __uctype __urngmax = __urng.max();
|
||||
const __uctype __urngrange = __urngmax - __urngmin;
|
||||
const __uctype __urange
|
||||
= __uctype(__param.b()) - __uctype(__param.a());
|
||||
|
||||
__uctype __ret;
|
||||
|
||||
if (__urngrange > __urange)
|
||||
{
|
||||
if (__detail::_Power_of_2(__urngrange + 1)
|
||||
&& __detail::_Power_of_2(__urange + 1))
|
||||
{
|
||||
while (__f != __t)
|
||||
{
|
||||
__ret = __uctype(__urng()) - __urngmin;
|
||||
*__f++ = (__ret & __urange) + __param.a();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// downscaling
|
||||
const __uctype __uerange = __urange + 1; // __urange can be zero
|
||||
const __uctype __scaling = __urngrange / __uerange;
|
||||
const __uctype __past = __uerange * __scaling;
|
||||
while (__f != __t)
|
||||
{
|
||||
do
|
||||
__ret = __uctype(__urng()) - __urngmin;
|
||||
while (__ret >= __past);
|
||||
*__f++ = __ret / __scaling + __param.a();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (__urngrange < __urange)
|
||||
{
|
||||
// upscaling
|
||||
/*
|
||||
Note that every value in [0, urange]
|
||||
can be written uniquely as
|
||||
|
||||
(urngrange + 1) * high + low
|
||||
|
||||
where
|
||||
|
||||
high in [0, urange / (urngrange + 1)]
|
||||
|
||||
and
|
||||
|
||||
low in [0, urngrange].
|
||||
*/
|
||||
__uctype __tmp; // wraparound control
|
||||
while (__f != __t)
|
||||
{
|
||||
do
|
||||
{
|
||||
const __uctype __uerngrange = __urngrange + 1;
|
||||
__tmp = (__uerngrange * operator()
|
||||
(__urng, param_type(0, __urange / __uerngrange)));
|
||||
__ret = __tmp + (__uctype(__urng()) - __urngmin);
|
||||
}
|
||||
while (__ret > __urange || __ret < __tmp);
|
||||
*__f++ = __ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
while (__f != __t)
|
||||
*__f++ = __uctype(__urng()) - __urngmin + __param.a();
|
||||
}
|
||||
|
||||
// operator!= and operator<< and operator>> are defined in <bits/random.h>
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,844 @@
|
|||
// unique_ptr implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2008-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/unique_ptr.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _UNIQUE_PTR_H
|
||||
#define _UNIQUE_PTR_H 1
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../debug/assertions.h"
|
||||
#include "../type_traits"
|
||||
#include "../utility"
|
||||
#include "../tuple"
|
||||
#include "../bits/stl_function.h"
|
||||
#include "../bits/functional_hash.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @addtogroup pointer_abstractions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if _GLIBCXX_USE_DEPRECATED
|
||||
template<typename> class auto_ptr;
|
||||
#endif
|
||||
|
||||
/// Primary template of default_delete, used by unique_ptr
|
||||
template<typename _Tp>
|
||||
struct default_delete
|
||||
{
|
||||
/// Default constructor
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
/** @brief Converting constructor.
|
||||
*
|
||||
* Allows conversion from a deleter for arrays of another type, @p _Up,
|
||||
* only if @p _Up* is convertible to @p _Tp*.
|
||||
*/
|
||||
template<typename _Up, typename = typename
|
||||
enable_if<is_convertible<_Up*, _Tp*>::value>::type>
|
||||
default_delete(const default_delete<_Up>&) noexcept { }
|
||||
|
||||
/// Calls @c delete @p __ptr
|
||||
void
|
||||
operator()(_Tp* __ptr) const
|
||||
{
|
||||
static_assert(!is_void<_Tp>::value,
|
||||
"can't delete pointer to incomplete type");
|
||||
static_assert(sizeof(_Tp)>0,
|
||||
"can't delete pointer to incomplete type");
|
||||
delete __ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// DR 740 - omit specialization for array objects with a compile time length
|
||||
/// Specialization for arrays, default_delete.
|
||||
template<typename _Tp>
|
||||
struct default_delete<_Tp[]>
|
||||
{
|
||||
public:
|
||||
/// Default constructor
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
/** @brief Converting constructor.
|
||||
*
|
||||
* Allows conversion from a deleter for arrays of another type, such as
|
||||
* a const-qualified version of @p _Tp.
|
||||
*
|
||||
* Conversions from types derived from @c _Tp are not allowed because
|
||||
* it is unsafe to @c delete[] an array of derived types through a
|
||||
* pointer to the base type.
|
||||
*/
|
||||
template<typename _Up, typename = typename
|
||||
enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type>
|
||||
default_delete(const default_delete<_Up[]>&) noexcept { }
|
||||
|
||||
/// Calls @c delete[] @p __ptr
|
||||
template<typename _Up>
|
||||
typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
|
||||
operator()(_Up* __ptr) const
|
||||
{
|
||||
static_assert(sizeof(_Tp)>0,
|
||||
"can't delete pointer to incomplete type");
|
||||
delete [] __ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _Tp, typename _Dp>
|
||||
class __uniq_ptr_impl
|
||||
{
|
||||
template <typename _Up, typename _Ep, typename = void>
|
||||
struct _Ptr
|
||||
{
|
||||
using type = _Up*;
|
||||
};
|
||||
|
||||
template <typename _Up, typename _Ep>
|
||||
struct
|
||||
_Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
|
||||
{
|
||||
using type = typename remove_reference<_Ep>::type::pointer;
|
||||
};
|
||||
|
||||
public:
|
||||
using _DeleterConstraint = enable_if<
|
||||
__and_<__not_<is_pointer<_Dp>>,
|
||||
is_default_constructible<_Dp>>::value>;
|
||||
|
||||
using pointer = typename _Ptr<_Tp, _Dp>::type;
|
||||
|
||||
__uniq_ptr_impl() = default;
|
||||
__uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
|
||||
|
||||
template<typename _Del>
|
||||
__uniq_ptr_impl(pointer __p, _Del&& __d)
|
||||
: _M_t(__p, std::forward<_Del>(__d)) { }
|
||||
|
||||
pointer& _M_ptr() { return std::get<0>(_M_t); }
|
||||
pointer _M_ptr() const { return std::get<0>(_M_t); }
|
||||
_Dp& _M_deleter() { return std::get<1>(_M_t); }
|
||||
const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
|
||||
|
||||
private:
|
||||
tuple<pointer, _Dp> _M_t;
|
||||
};
|
||||
|
||||
/// 20.7.1.2 unique_ptr for single objects.
|
||||
template <typename _Tp, typename _Dp = default_delete<_Tp>>
|
||||
class unique_ptr
|
||||
{
|
||||
template <class _Up>
|
||||
using _DeleterConstraint =
|
||||
typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
|
||||
|
||||
__uniq_ptr_impl<_Tp, _Dp> _M_t;
|
||||
|
||||
public:
|
||||
using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
|
||||
using element_type = _Tp;
|
||||
using deleter_type = _Dp;
|
||||
|
||||
// helper template for detecting a safe conversion from another
|
||||
// unique_ptr
|
||||
template<typename _Up, typename _Ep>
|
||||
using __safe_conversion_up = __and_<
|
||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
|
||||
__not_<is_array<_Up>>,
|
||||
__or_<__and_<is_reference<deleter_type>,
|
||||
is_same<deleter_type, _Ep>>,
|
||||
__and_<__not_<is_reference<deleter_type>>,
|
||||
is_convertible<_Ep, deleter_type>>
|
||||
>
|
||||
>;
|
||||
|
||||
// Constructors.
|
||||
|
||||
/// Default constructor, creates a unique_ptr that owns nothing.
|
||||
template <typename _Up = _Dp,
|
||||
typename = _DeleterConstraint<_Up>>
|
||||
constexpr unique_ptr() noexcept
|
||||
: _M_t()
|
||||
{ }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an object of @c element_type
|
||||
*
|
||||
* The deleter will be value-initialized.
|
||||
*/
|
||||
template <typename _Up = _Dp,
|
||||
typename = _DeleterConstraint<_Up>>
|
||||
explicit
|
||||
unique_ptr(pointer __p) noexcept
|
||||
: _M_t(__p)
|
||||
{ }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an object of @c element_type
|
||||
* @param __d A reference to a deleter.
|
||||
*
|
||||
* The deleter will be initialized with @p __d
|
||||
*/
|
||||
unique_ptr(pointer __p,
|
||||
typename conditional<is_reference<deleter_type>::value,
|
||||
deleter_type, const deleter_type&>::type __d) noexcept
|
||||
: _M_t(__p, __d) { }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an object of @c element_type
|
||||
* @param __d An rvalue reference to a deleter.
|
||||
*
|
||||
* The deleter will be initialized with @p std::move(__d)
|
||||
*/
|
||||
unique_ptr(pointer __p,
|
||||
typename remove_reference<deleter_type>::type&& __d) noexcept
|
||||
: _M_t(std::move(__p), std::move(__d))
|
||||
{ static_assert(!std::is_reference<deleter_type>::value,
|
||||
"rvalue deleter bound to reference"); }
|
||||
|
||||
/// Creates a unique_ptr that owns nothing.
|
||||
template <typename _Up = _Dp,
|
||||
typename = _DeleterConstraint<_Up>>
|
||||
constexpr unique_ptr(nullptr_t) noexcept : _M_t() { }
|
||||
|
||||
// Move constructors.
|
||||
|
||||
/// Move constructor.
|
||||
unique_ptr(unique_ptr&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
|
||||
|
||||
/** @brief Converting constructor from another type
|
||||
*
|
||||
* Requires that the pointer owned by @p __u is convertible to the
|
||||
* type of pointer owned by this object, @p __u does not own an array,
|
||||
* and @p __u has a compatible deleter type.
|
||||
*/
|
||||
template<typename _Up, typename _Ep, typename = _Require<
|
||||
__safe_conversion_up<_Up, _Ep>,
|
||||
typename conditional<is_reference<_Dp>::value,
|
||||
is_same<_Ep, _Dp>,
|
||||
is_convertible<_Ep, _Dp>>::type>>
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
||||
{ }
|
||||
|
||||
#if _GLIBCXX_USE_DEPRECATED
|
||||
/// Converting constructor from @c auto_ptr
|
||||
template<typename _Up, typename = _Require<
|
||||
is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
|
||||
unique_ptr(auto_ptr<_Up>&& __u) noexcept;
|
||||
#endif
|
||||
|
||||
/// Destructor, invokes the deleter if the stored pointer is not null.
|
||||
~unique_ptr() noexcept
|
||||
{
|
||||
auto& __ptr = _M_t._M_ptr();
|
||||
if (__ptr != nullptr)
|
||||
get_deleter()(__ptr);
|
||||
__ptr = pointer();
|
||||
}
|
||||
|
||||
// Assignment.
|
||||
|
||||
/** @brief Move assignment operator.
|
||||
*
|
||||
* @param __u The object to transfer ownership from.
|
||||
*
|
||||
* Invokes the deleter first if this object owns a pointer.
|
||||
*/
|
||||
unique_ptr&
|
||||
operator=(unique_ptr&& __u) noexcept
|
||||
{
|
||||
reset(__u.release());
|
||||
get_deleter() = std::forward<deleter_type>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Assignment from another type.
|
||||
*
|
||||
* @param __u The object to transfer ownership from, which owns a
|
||||
* convertible pointer to a non-array object.
|
||||
*
|
||||
* Invokes the deleter first if this object owns a pointer.
|
||||
*/
|
||||
template<typename _Up, typename _Ep>
|
||||
typename enable_if< __and_<
|
||||
__safe_conversion_up<_Up, _Ep>,
|
||||
is_assignable<deleter_type&, _Ep&&>
|
||||
>::value,
|
||||
unique_ptr&>::type
|
||||
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
{
|
||||
reset(__u.release());
|
||||
get_deleter() = std::forward<_Ep>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Reset the %unique_ptr to empty, invoking the deleter if necessary.
|
||||
unique_ptr&
|
||||
operator=(nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Observers.
|
||||
|
||||
/// Dereference the stored pointer.
|
||||
typename add_lvalue_reference<element_type>::type
|
||||
operator*() const
|
||||
{
|
||||
__glibcxx_assert(get() != pointer());
|
||||
return *get();
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
_GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
|
||||
return get();
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
pointer
|
||||
get() const noexcept
|
||||
{ return _M_t._M_ptr(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
deleter_type&
|
||||
get_deleter() noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
const deleter_type&
|
||||
get_deleter() const noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return @c true if the stored pointer is not null.
|
||||
explicit operator bool() const noexcept
|
||||
{ return get() == pointer() ? false : true; }
|
||||
|
||||
// Modifiers.
|
||||
|
||||
/// Release ownership of any stored pointer.
|
||||
pointer
|
||||
release() noexcept
|
||||
{
|
||||
pointer __p = get();
|
||||
_M_t._M_ptr() = pointer();
|
||||
return __p;
|
||||
}
|
||||
|
||||
/** @brief Replace the stored pointer.
|
||||
*
|
||||
* @param __p The new pointer to store.
|
||||
*
|
||||
* The deleter will be invoked if a pointer is already owned.
|
||||
*/
|
||||
void
|
||||
reset(pointer __p = pointer()) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(_M_t._M_ptr(), __p);
|
||||
if (__p != pointer())
|
||||
get_deleter()(__p);
|
||||
}
|
||||
|
||||
/// Exchange the pointer and deleter with another object.
|
||||
void
|
||||
swap(unique_ptr& __u) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(_M_t, __u._M_t);
|
||||
}
|
||||
|
||||
// Disable copy from lvalue.
|
||||
unique_ptr(const unique_ptr&) = delete;
|
||||
unique_ptr& operator=(const unique_ptr&) = delete;
|
||||
};
|
||||
|
||||
/// 20.7.1.3 unique_ptr for array objects with a runtime length
|
||||
// [unique.ptr.runtime]
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// DR 740 - omit specialization for array objects with a compile time length
|
||||
template<typename _Tp, typename _Dp>
|
||||
class unique_ptr<_Tp[], _Dp>
|
||||
{
|
||||
template <typename _Up>
|
||||
using _DeleterConstraint =
|
||||
typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
|
||||
|
||||
__uniq_ptr_impl<_Tp, _Dp> _M_t;
|
||||
|
||||
template<typename _Up>
|
||||
using __remove_cv = typename remove_cv<_Up>::type;
|
||||
|
||||
// like is_base_of<_Tp, _Up> but false if unqualified types are the same
|
||||
template<typename _Up>
|
||||
using __is_derived_Tp
|
||||
= __and_< is_base_of<_Tp, _Up>,
|
||||
__not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
|
||||
|
||||
public:
|
||||
using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
|
||||
using element_type = _Tp;
|
||||
using deleter_type = _Dp;
|
||||
|
||||
// helper template for detecting a safe conversion from another
|
||||
// unique_ptr
|
||||
template<typename _Up, typename _Ep,
|
||||
typename _Up_up = unique_ptr<_Up, _Ep>,
|
||||
typename _Up_element_type = typename _Up_up::element_type>
|
||||
using __safe_conversion_up = __and_<
|
||||
is_array<_Up>,
|
||||
is_same<pointer, element_type*>,
|
||||
is_same<typename _Up_up::pointer, _Up_element_type*>,
|
||||
is_convertible<_Up_element_type(*)[], element_type(*)[]>,
|
||||
__or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>,
|
||||
__and_<__not_<is_reference<deleter_type>>,
|
||||
is_convertible<_Ep, deleter_type>>>
|
||||
>;
|
||||
|
||||
// helper template for detecting a safe conversion from a raw pointer
|
||||
template<typename _Up>
|
||||
using __safe_conversion_raw = __and_<
|
||||
__or_<__or_<is_same<_Up, pointer>,
|
||||
is_same<_Up, nullptr_t>>,
|
||||
__and_<is_pointer<_Up>,
|
||||
is_same<pointer, element_type*>,
|
||||
is_convertible<
|
||||
typename remove_pointer<_Up>::type(*)[],
|
||||
element_type(*)[]>
|
||||
>
|
||||
>
|
||||
>;
|
||||
|
||||
// Constructors.
|
||||
|
||||
/// Default constructor, creates a unique_ptr that owns nothing.
|
||||
template <typename _Up = _Dp,
|
||||
typename = _DeleterConstraint<_Up>>
|
||||
constexpr unique_ptr() noexcept
|
||||
: _M_t()
|
||||
{ }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an array of a type safely convertible
|
||||
* to an array of @c element_type
|
||||
*
|
||||
* The deleter will be value-initialized.
|
||||
*/
|
||||
template<typename _Up,
|
||||
typename _Vp = _Dp,
|
||||
typename = _DeleterConstraint<_Vp>,
|
||||
typename = typename enable_if<
|
||||
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||
explicit
|
||||
unique_ptr(_Up __p) noexcept
|
||||
: _M_t(__p)
|
||||
{ }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an array of a type safely convertible
|
||||
* to an array of @c element_type
|
||||
* @param __d A reference to a deleter.
|
||||
*
|
||||
* The deleter will be initialized with @p __d
|
||||
*/
|
||||
template<typename _Up,
|
||||
typename = typename enable_if<
|
||||
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||
unique_ptr(_Up __p,
|
||||
typename conditional<is_reference<deleter_type>::value,
|
||||
deleter_type, const deleter_type&>::type __d) noexcept
|
||||
: _M_t(__p, __d) { }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
* @param __p A pointer to an array of a type safely convertible
|
||||
* to an array of @c element_type
|
||||
* @param __d A reference to a deleter.
|
||||
*
|
||||
* The deleter will be initialized with @p std::move(__d)
|
||||
*/
|
||||
template<typename _Up,
|
||||
typename = typename enable_if<
|
||||
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||
unique_ptr(_Up __p, typename
|
||||
remove_reference<deleter_type>::type&& __d) noexcept
|
||||
: _M_t(std::move(__p), std::move(__d))
|
||||
{ static_assert(!is_reference<deleter_type>::value,
|
||||
"rvalue deleter bound to reference"); }
|
||||
|
||||
/// Move constructor.
|
||||
unique_ptr(unique_ptr&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
|
||||
|
||||
/// Creates a unique_ptr that owns nothing.
|
||||
template <typename _Up = _Dp,
|
||||
typename = _DeleterConstraint<_Up>>
|
||||
constexpr unique_ptr(nullptr_t) noexcept : _M_t() { }
|
||||
|
||||
template<typename _Up, typename _Ep,
|
||||
typename = _Require<__safe_conversion_up<_Up, _Ep>>>
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
||||
{ }
|
||||
|
||||
/// Destructor, invokes the deleter if the stored pointer is not null.
|
||||
~unique_ptr()
|
||||
{
|
||||
auto& __ptr = _M_t._M_ptr();
|
||||
if (__ptr != nullptr)
|
||||
get_deleter()(__ptr);
|
||||
__ptr = pointer();
|
||||
}
|
||||
|
||||
// Assignment.
|
||||
|
||||
/** @brief Move assignment operator.
|
||||
*
|
||||
* @param __u The object to transfer ownership from.
|
||||
*
|
||||
* Invokes the deleter first if this object owns a pointer.
|
||||
*/
|
||||
unique_ptr&
|
||||
operator=(unique_ptr&& __u) noexcept
|
||||
{
|
||||
reset(__u.release());
|
||||
get_deleter() = std::forward<deleter_type>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Assignment from another type.
|
||||
*
|
||||
* @param __u The object to transfer ownership from, which owns a
|
||||
* convertible pointer to an array object.
|
||||
*
|
||||
* Invokes the deleter first if this object owns a pointer.
|
||||
*/
|
||||
template<typename _Up, typename _Ep>
|
||||
typename
|
||||
enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
|
||||
is_assignable<deleter_type&, _Ep&&>
|
||||
>::value,
|
||||
unique_ptr&>::type
|
||||
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
{
|
||||
reset(__u.release());
|
||||
get_deleter() = std::forward<_Ep>(__u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Reset the %unique_ptr to empty, invoking the deleter if necessary.
|
||||
unique_ptr&
|
||||
operator=(nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Observers.
|
||||
|
||||
/// Access an element of owned array.
|
||||
typename std::add_lvalue_reference<element_type>::type
|
||||
operator[](size_t __i) const
|
||||
{
|
||||
__glibcxx_assert(get() != pointer());
|
||||
return get()[__i];
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
pointer
|
||||
get() const noexcept
|
||||
{ return _M_t._M_ptr(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
deleter_type&
|
||||
get_deleter() noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
const deleter_type&
|
||||
get_deleter() const noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return @c true if the stored pointer is not null.
|
||||
explicit operator bool() const noexcept
|
||||
{ return get() == pointer() ? false : true; }
|
||||
|
||||
// Modifiers.
|
||||
|
||||
/// Release ownership of any stored pointer.
|
||||
pointer
|
||||
release() noexcept
|
||||
{
|
||||
pointer __p = get();
|
||||
_M_t._M_ptr() = pointer();
|
||||
return __p;
|
||||
}
|
||||
|
||||
/** @brief Replace the stored pointer.
|
||||
*
|
||||
* @param __p The new pointer to store.
|
||||
*
|
||||
* The deleter will be invoked if a pointer is already owned.
|
||||
*/
|
||||
template <typename _Up,
|
||||
typename = _Require<
|
||||
__or_<is_same<_Up, pointer>,
|
||||
__and_<is_same<pointer, element_type*>,
|
||||
is_pointer<_Up>,
|
||||
is_convertible<
|
||||
typename remove_pointer<_Up>::type(*)[],
|
||||
element_type(*)[]
|
||||
>
|
||||
>
|
||||
>
|
||||
>>
|
||||
void
|
||||
reset(_Up __p) noexcept
|
||||
{
|
||||
pointer __ptr = __p;
|
||||
using std::swap;
|
||||
swap(_M_t._M_ptr(), __ptr);
|
||||
if (__ptr != nullptr)
|
||||
get_deleter()(__ptr);
|
||||
}
|
||||
|
||||
void reset(nullptr_t = nullptr) noexcept
|
||||
{
|
||||
reset(pointer());
|
||||
}
|
||||
|
||||
/// Exchange the pointer and deleter with another object.
|
||||
void
|
||||
swap(unique_ptr& __u) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(_M_t, __u._M_t);
|
||||
}
|
||||
|
||||
// Disable copy from lvalue.
|
||||
unique_ptr(const unique_ptr&) = delete;
|
||||
unique_ptr& operator=(const unique_ptr&) = delete;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
// Constrained free swap overload, see p0185r1
|
||||
typename enable_if<__is_swappable<_Dp>::value>::type
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
swap(unique_ptr<_Tp, _Dp>& __x,
|
||||
unique_ptr<_Tp, _Dp>& __y) noexcept
|
||||
{ __x.swap(__y); }
|
||||
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
template<typename _Tp, typename _Dp>
|
||||
typename enable_if<!__is_swappable<_Dp>::value>::type
|
||||
swap(unique_ptr<_Tp, _Dp>&,
|
||||
unique_ptr<_Tp, _Dp>&) = delete;
|
||||
#endif
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator==(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return __x.get() == __y.get(); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
|
||||
{ return !__x; }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
|
||||
{ return !__x; }
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator!=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return __x.get() != __y.get(); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
|
||||
{ return (bool)__x; }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
|
||||
{ return (bool)__x; }
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator<(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{
|
||||
typedef typename
|
||||
std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
|
||||
typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
|
||||
return std::less<_CT>()(__x.get(), __y.get());
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
|
||||
nullptr); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{ return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
|
||||
__x.get()); }
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator<=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return !(__y < __x); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return !(nullptr < __x); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{ return !(__x < nullptr); }
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator>(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return (__y < __x); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
|
||||
__x.get()); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{ return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
|
||||
nullptr); }
|
||||
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
inline bool
|
||||
operator>=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return !(__x < __y); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return !(__x < nullptr); }
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
inline bool
|
||||
operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{ return !(nullptr < __x); }
|
||||
|
||||
/// std::hash specialization for unique_ptr.
|
||||
template<typename _Tp, typename _Dp>
|
||||
struct hash<unique_ptr<_Tp, _Dp>>
|
||||
: public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
|
||||
private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer>
|
||||
{
|
||||
size_t
|
||||
operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
|
||||
{
|
||||
typedef unique_ptr<_Tp, _Dp> _UP;
|
||||
return std::hash<typename _UP::pointer>()(__u.get());
|
||||
}
|
||||
};
|
||||
|
||||
#if __cplusplus > 201103L
|
||||
|
||||
#define __cpp_lib_make_unique 201304
|
||||
|
||||
template<typename _Tp>
|
||||
struct _MakeUniq
|
||||
{ typedef unique_ptr<_Tp> __single_object; };
|
||||
|
||||
template<typename _Tp>
|
||||
struct _MakeUniq<_Tp[]>
|
||||
{ typedef unique_ptr<_Tp[]> __array; };
|
||||
|
||||
template<typename _Tp, size_t _Bound>
|
||||
struct _MakeUniq<_Tp[_Bound]>
|
||||
{ struct __invalid_type { }; };
|
||||
|
||||
/// std::make_unique for single objects
|
||||
template<typename _Tp, typename... _Args>
|
||||
inline typename _MakeUniq<_Tp>::__single_object
|
||||
make_unique(_Args&&... __args)
|
||||
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
|
||||
|
||||
/// std::make_unique for arrays of unknown bound
|
||||
template<typename _Tp>
|
||||
inline typename _MakeUniq<_Tp>::__array
|
||||
make_unique(size_t __num)
|
||||
{ return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
|
||||
|
||||
/// Disable std::make_unique for arrays of known bound
|
||||
template<typename _Tp, typename... _Args>
|
||||
inline typename _MakeUniq<_Tp>::__invalid_type
|
||||
make_unique(_Args&&...) = delete;
|
||||
#endif
|
||||
|
||||
// @} group pointer_abstractions
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif /* _UNIQUE_PTR_H */
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// Uses-allocator Construction -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2010-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _USES_ALLOCATOR_H
|
||||
#define _USES_ALLOCATOR_H 1
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include "../bits/c++0x_warning.h"
|
||||
#else
|
||||
|
||||
#include "../type_traits"
|
||||
#include "../bits/move.h"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct __erased_type { };
|
||||
|
||||
template<typename _Alloc, typename _Tp>
|
||||
using __is_erased_or_convertible
|
||||
= __or_<is_same<_Tp, __erased_type>, is_convertible<_Alloc, _Tp>>;
|
||||
|
||||
/// [allocator.tag]
|
||||
struct allocator_arg_t { explicit allocator_arg_t() = default; };
|
||||
|
||||
_GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
|
||||
allocator_arg_t();
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename = __void_t<>>
|
||||
struct __uses_allocator_helper
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
struct __uses_allocator_helper<_Tp, _Alloc,
|
||||
__void_t<typename _Tp::allocator_type>>
|
||||
: __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
|
||||
{ };
|
||||
|
||||
/// [allocator.uses.trait]
|
||||
template<typename _Tp, typename _Alloc>
|
||||
struct uses_allocator
|
||||
: __uses_allocator_helper<_Tp, _Alloc>::type
|
||||
{ };
|
||||
|
||||
struct __uses_alloc_base { };
|
||||
|
||||
struct __uses_alloc0 : __uses_alloc_base
|
||||
{
|
||||
struct _Sink { void operator=(const void*) { } } _M_a;
|
||||
};
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
|
||||
|
||||
template<typename _Alloc>
|
||||
struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
|
||||
|
||||
template<bool, typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __uses_alloc;
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __uses_alloc<true, _Tp, _Alloc, _Args...>
|
||||
: conditional<
|
||||
is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value,
|
||||
__uses_alloc1<_Alloc>,
|
||||
__uses_alloc2<_Alloc>>::type
|
||||
{
|
||||
static_assert(__or_<
|
||||
is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>,
|
||||
is_constructible<_Tp, _Args..., _Alloc>>::value, "construction with"
|
||||
" an allocator must be possible if uses_allocator is true");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __uses_alloc<false, _Tp, _Alloc, _Args...>
|
||||
: __uses_alloc0 { };
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
using __uses_alloc_t =
|
||||
__uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
inline __uses_alloc_t<_Tp, _Alloc, _Args...>
|
||||
__use_alloc(const _Alloc& __a)
|
||||
{
|
||||
__uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
|
||||
__ret._M_a = std::__addressof(__a);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
void
|
||||
__use_alloc(const _Alloc&&) = delete;
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
template <typename _Tp, typename _Alloc>
|
||||
inline constexpr bool uses_allocator_v =
|
||||
uses_allocator<_Tp, _Alloc>::value;
|
||||
#endif // C++17
|
||||
|
||||
template<template<typename...> class _Predicate,
|
||||
typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __is_uses_allocator_predicate
|
||||
: conditional<uses_allocator<_Tp, _Alloc>::value,
|
||||
__or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
|
||||
_Predicate<_Tp, _Args..., _Alloc>>,
|
||||
_Predicate<_Tp, _Args...>>::type { };
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __is_uses_allocator_constructible
|
||||
: __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
|
||||
{ };
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
_GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
|
||||
__is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
|
||||
#endif // C++14
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
struct __is_nothrow_uses_allocator_constructible
|
||||
: __is_uses_allocator_predicate<is_nothrow_constructible,
|
||||
_Tp, _Alloc, _Args...>
|
||||
{ };
|
||||
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
_GLIBCXX17_INLINE constexpr bool
|
||||
__is_nothrow_uses_allocator_constructible_v =
|
||||
__is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
|
||||
#endif // C++14
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr,
|
||||
_Args&&... __args)
|
||||
{ ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
|
||||
_Args&&... __args)
|
||||
{
|
||||
::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
|
||||
_Args&&... __args)
|
||||
{ ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
|
||||
|
||||
template<typename _Tp, typename _Alloc, typename... _Args>
|
||||
void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
|
||||
_Args&&... __args)
|
||||
{
|
||||
__uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a),
|
||||
__ptr, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,905 @@
|
|||
// Vector implementation (out of line) -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file bits/vector.tcc
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{vector}
|
||||
*/
|
||||
|
||||
#ifndef _VECTOR_TCC
|
||||
#define _VECTOR_TCC 1
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
reserve(size_type __n)
|
||||
{
|
||||
if (__n > this->max_size())
|
||||
__throw_length_error(__N("vector::reserve"));
|
||||
if (this->capacity() < __n)
|
||||
{
|
||||
const size_type __old_size = size();
|
||||
pointer __tmp = _M_allocate_and_copy(__n,
|
||||
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
|
||||
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __tmp;
|
||||
this->_M_impl._M_finish = __tmp + __old_size;
|
||||
this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename... _Args>
|
||||
#if __cplusplus > 201402L
|
||||
typename vector<_Tp, _Alloc>::reference
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
vector<_Tp, _Alloc>::
|
||||
emplace_back(_Args&&... __args)
|
||||
{
|
||||
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
|
||||
{
|
||||
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
|
||||
std::forward<_Args>(__args)...);
|
||||
++this->_M_impl._M_finish;
|
||||
}
|
||||
else
|
||||
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
|
||||
#if __cplusplus > 201402L
|
||||
return back();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
typename vector<_Tp, _Alloc>::iterator
|
||||
vector<_Tp, _Alloc>::
|
||||
#if __cplusplus >= 201103L
|
||||
insert(const_iterator __position, const value_type& __x)
|
||||
#else
|
||||
insert(iterator __position, const value_type& __x)
|
||||
#endif
|
||||
{
|
||||
const size_type __n = __position - begin();
|
||||
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
|
||||
if (__position == end())
|
||||
{
|
||||
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
|
||||
__x);
|
||||
++this->_M_impl._M_finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
const auto __pos = begin() + (__position - cbegin());
|
||||
// __x could be an existing element of this vector, so make a
|
||||
// copy of it before _M_insert_aux moves elements around.
|
||||
_Temporary_value __x_copy(this, __x);
|
||||
_M_insert_aux(__pos, std::move(__x_copy._M_val()));
|
||||
#else
|
||||
_M_insert_aux(__position, __x);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#if __cplusplus >= 201103L
|
||||
_M_realloc_insert(begin() + (__position - cbegin()), __x);
|
||||
#else
|
||||
_M_realloc_insert(__position, __x);
|
||||
#endif
|
||||
|
||||
return iterator(this->_M_impl._M_start + __n);
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
typename vector<_Tp, _Alloc>::iterator
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_erase(iterator __position)
|
||||
{
|
||||
if (__position + 1 != end())
|
||||
_GLIBCXX_MOVE3(__position + 1, end(), __position);
|
||||
--this->_M_impl._M_finish;
|
||||
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
|
||||
return __position;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
typename vector<_Tp, _Alloc>::iterator
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_erase(iterator __first, iterator __last)
|
||||
{
|
||||
if (__first != __last)
|
||||
{
|
||||
if (__last != end())
|
||||
_GLIBCXX_MOVE3(__last, end(), __first);
|
||||
_M_erase_at_end(__first.base() + (end() - __last));
|
||||
}
|
||||
return __first;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
vector<_Tp, _Alloc>&
|
||||
vector<_Tp, _Alloc>::
|
||||
operator=(const vector<_Tp, _Alloc>& __x)
|
||||
{
|
||||
if (&__x != this)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
if (_Alloc_traits::_S_propagate_on_copy_assign())
|
||||
{
|
||||
if (!_Alloc_traits::_S_always_equal()
|
||||
&& _M_get_Tp_allocator() != __x._M_get_Tp_allocator())
|
||||
{
|
||||
// replacement allocator cannot free existing storage
|
||||
this->clear();
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = nullptr;
|
||||
this->_M_impl._M_finish = nullptr;
|
||||
this->_M_impl._M_end_of_storage = nullptr;
|
||||
}
|
||||
std::__alloc_on_copy(_M_get_Tp_allocator(),
|
||||
__x._M_get_Tp_allocator());
|
||||
}
|
||||
#endif
|
||||
const size_type __xlen = __x.size();
|
||||
if (__xlen > capacity())
|
||||
{
|
||||
pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(),
|
||||
__x.end());
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __tmp;
|
||||
this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen;
|
||||
}
|
||||
else if (size() >= __xlen)
|
||||
{
|
||||
std::_Destroy(std::copy(__x.begin(), __x.end(), begin()),
|
||||
end(), _M_get_Tp_allocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(),
|
||||
this->_M_impl._M_start);
|
||||
std::__uninitialized_copy_a(__x._M_impl._M_start + size(),
|
||||
__x._M_impl._M_finish,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
}
|
||||
this->_M_impl._M_finish = this->_M_impl._M_start + __xlen;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_fill_assign(size_t __n, const value_type& __val)
|
||||
{
|
||||
if (__n > capacity())
|
||||
{
|
||||
vector __tmp(__n, __val, _M_get_Tp_allocator());
|
||||
__tmp._M_impl._M_swap_data(this->_M_impl);
|
||||
}
|
||||
else if (__n > size())
|
||||
{
|
||||
std::fill(begin(), end(), __val);
|
||||
this->_M_impl._M_finish =
|
||||
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
|
||||
__n - size(), __val,
|
||||
_M_get_Tp_allocator());
|
||||
}
|
||||
else
|
||||
_M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename _InputIterator>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_assign_aux(_InputIterator __first, _InputIterator __last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
pointer __cur(this->_M_impl._M_start);
|
||||
for (; __first != __last && __cur != this->_M_impl._M_finish;
|
||||
++__cur, ++__first)
|
||||
*__cur = *__first;
|
||||
if (__first == __last)
|
||||
_M_erase_at_end(__cur);
|
||||
else
|
||||
_M_range_insert(end(), __first, __last,
|
||||
std::__iterator_category(__first));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename _ForwardIterator>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
const size_type __len = std::distance(__first, __last);
|
||||
|
||||
if (__len > capacity())
|
||||
{
|
||||
pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __tmp;
|
||||
this->_M_impl._M_finish = this->_M_impl._M_start + __len;
|
||||
this->_M_impl._M_end_of_storage = this->_M_impl._M_finish;
|
||||
}
|
||||
else if (size() >= __len)
|
||||
_M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start));
|
||||
else
|
||||
{
|
||||
_ForwardIterator __mid = __first;
|
||||
std::advance(__mid, size());
|
||||
std::copy(__first, __mid, this->_M_impl._M_start);
|
||||
this->_M_impl._M_finish =
|
||||
std::__uninitialized_copy_a(__mid, __last,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, typename _Alloc>
|
||||
auto
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_insert_rval(const_iterator __position, value_type&& __v) -> iterator
|
||||
{
|
||||
const auto __n = __position - cbegin();
|
||||
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
|
||||
if (__position == cend())
|
||||
{
|
||||
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
|
||||
std::move(__v));
|
||||
++this->_M_impl._M_finish;
|
||||
}
|
||||
else
|
||||
_M_insert_aux(begin() + __n, std::move(__v));
|
||||
else
|
||||
_M_realloc_insert(begin() + __n, std::move(__v));
|
||||
|
||||
return iterator(this->_M_impl._M_start + __n);
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename... _Args>
|
||||
auto
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_emplace_aux(const_iterator __position, _Args&&... __args)
|
||||
-> iterator
|
||||
{
|
||||
const auto __n = __position - cbegin();
|
||||
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
|
||||
if (__position == cend())
|
||||
{
|
||||
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
|
||||
std::forward<_Args>(__args)...);
|
||||
++this->_M_impl._M_finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to construct a temporary because something in __args...
|
||||
// could alias one of the elements of the container and so we
|
||||
// need to use it before _M_insert_aux moves elements around.
|
||||
_Temporary_value __tmp(this, std::forward<_Args>(__args)...);
|
||||
_M_insert_aux(begin() + __n, std::move(__tmp._M_val()));
|
||||
}
|
||||
else
|
||||
_M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...);
|
||||
|
||||
return iterator(this->_M_impl._M_start + __n);
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename _Arg>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_insert_aux(iterator __position, _Arg&& __arg)
|
||||
#else
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_insert_aux(iterator __position, const _Tp& __x)
|
||||
#endif
|
||||
{
|
||||
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
|
||||
_GLIBCXX_MOVE(*(this->_M_impl._M_finish
|
||||
- 1)));
|
||||
++this->_M_impl._M_finish;
|
||||
#if __cplusplus < 201103L
|
||||
_Tp __x_copy = __x;
|
||||
#endif
|
||||
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
|
||||
this->_M_impl._M_finish - 2,
|
||||
this->_M_impl._M_finish - 1);
|
||||
#if __cplusplus < 201103L
|
||||
*__position = __x_copy;
|
||||
#else
|
||||
*__position = std::forward<_Arg>(__arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename... _Args>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_realloc_insert(iterator __position, _Args&&... __args)
|
||||
#else
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_realloc_insert(iterator __position, const _Tp& __x)
|
||||
#endif
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(size_type(1), "vector::_M_realloc_insert");
|
||||
const size_type __elems_before = __position - begin();
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __new_finish(__new_start);
|
||||
__try
|
||||
{
|
||||
// The order of the three operations is dictated by the C++11
|
||||
// case, where the moves could alter a new element belonging
|
||||
// to the existing vector. This is an issue only for callers
|
||||
// taking the element by lvalue ref (see last bullet of C++11
|
||||
// [res.on.arguments]).
|
||||
_Alloc_traits::construct(this->_M_impl,
|
||||
__new_start + __elems_before,
|
||||
#if __cplusplus >= 201103L
|
||||
std::forward<_Args>(__args)...);
|
||||
#else
|
||||
__x);
|
||||
#endif
|
||||
__new_finish = pointer();
|
||||
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(this->_M_impl._M_start, __position.base(),
|
||||
__new_start, _M_get_Tp_allocator());
|
||||
|
||||
++__new_finish;
|
||||
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(__position.base(), this->_M_impl._M_finish,
|
||||
__new_finish, _M_get_Tp_allocator());
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
if (!__new_finish)
|
||||
_Alloc_traits::destroy(this->_M_impl,
|
||||
__new_start + __elems_before);
|
||||
else
|
||||
std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __new_start;
|
||||
this->_M_impl._M_finish = __new_finish;
|
||||
this->_M_impl._M_end_of_storage = __new_start + __len;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_fill_insert(iterator __position, size_type __n, const value_type& __x)
|
||||
{
|
||||
if (__n != 0)
|
||||
{
|
||||
if (size_type(this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_finish) >= __n)
|
||||
{
|
||||
#if __cplusplus < 201103L
|
||||
value_type __x_copy = __x;
|
||||
#else
|
||||
_Temporary_value __tmp(this, __x);
|
||||
value_type& __x_copy = __tmp._M_val();
|
||||
#endif
|
||||
const size_type __elems_after = end() - __position;
|
||||
pointer __old_finish(this->_M_impl._M_finish);
|
||||
if (__elems_after > __n)
|
||||
{
|
||||
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
|
||||
this->_M_impl._M_finish,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
this->_M_impl._M_finish += __n;
|
||||
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
|
||||
__old_finish - __n, __old_finish);
|
||||
std::fill(__position.base(), __position.base() + __n,
|
||||
__x_copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_M_impl._M_finish =
|
||||
std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
|
||||
__n - __elems_after,
|
||||
__x_copy,
|
||||
_M_get_Tp_allocator());
|
||||
std::__uninitialized_move_a(__position.base(), __old_finish,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
this->_M_impl._M_finish += __elems_after;
|
||||
std::fill(__position.base(), __old_finish, __x_copy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector::_M_fill_insert");
|
||||
const size_type __elems_before = __position - begin();
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __new_finish(__new_start);
|
||||
__try
|
||||
{
|
||||
// See _M_realloc_insert above.
|
||||
std::__uninitialized_fill_n_a(__new_start + __elems_before,
|
||||
__n, __x,
|
||||
_M_get_Tp_allocator());
|
||||
__new_finish = pointer();
|
||||
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(this->_M_impl._M_start, __position.base(),
|
||||
__new_start, _M_get_Tp_allocator());
|
||||
|
||||
__new_finish += __n;
|
||||
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(__position.base(), this->_M_impl._M_finish,
|
||||
__new_finish, _M_get_Tp_allocator());
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
if (!__new_finish)
|
||||
std::_Destroy(__new_start + __elems_before,
|
||||
__new_start + __elems_before + __n,
|
||||
_M_get_Tp_allocator());
|
||||
else
|
||||
std::_Destroy(__new_start, __new_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __new_start;
|
||||
this->_M_impl._M_finish = __new_finish;
|
||||
this->_M_impl._M_end_of_storage = __new_start + __len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Tp, typename _Alloc>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_default_append(size_type __n)
|
||||
{
|
||||
if (__n != 0)
|
||||
{
|
||||
if (size_type(this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_finish) >= __n)
|
||||
{
|
||||
this->_M_impl._M_finish =
|
||||
std::__uninitialized_default_n_a(this->_M_impl._M_finish,
|
||||
__n, _M_get_Tp_allocator());
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector::_M_default_append");
|
||||
const size_type __size = this->size();
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __destroy_from = pointer();
|
||||
__try
|
||||
{
|
||||
std::__uninitialized_default_n_a(__new_start + __size,
|
||||
__n, _M_get_Tp_allocator());
|
||||
__destroy_from = __new_start + __size;
|
||||
std::__uninitialized_move_if_noexcept_a(
|
||||
this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
__new_start, _M_get_Tp_allocator());
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
if (__destroy_from)
|
||||
std::_Destroy(__destroy_from, __destroy_from + __n,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __new_start;
|
||||
this->_M_impl._M_finish = __new_start + __size + __n;
|
||||
this->_M_impl._M_end_of_storage = __new_start + __len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
bool
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_shrink_to_fit()
|
||||
{
|
||||
if (capacity() == size())
|
||||
return false;
|
||||
return std::__shrink_to_fit_aux<vector>::_S_do_it(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename _InputIterator>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_range_insert(iterator __pos, _InputIterator __first,
|
||||
_InputIterator __last, std::input_iterator_tag)
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
{
|
||||
__pos = insert(__pos, *__first);
|
||||
++__pos;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Alloc>
|
||||
template<typename _ForwardIterator>
|
||||
void
|
||||
vector<_Tp, _Alloc>::
|
||||
_M_range_insert(iterator __position, _ForwardIterator __first,
|
||||
_ForwardIterator __last, std::forward_iterator_tag)
|
||||
{
|
||||
if (__first != __last)
|
||||
{
|
||||
const size_type __n = std::distance(__first, __last);
|
||||
if (size_type(this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_finish) >= __n)
|
||||
{
|
||||
const size_type __elems_after = end() - __position;
|
||||
pointer __old_finish(this->_M_impl._M_finish);
|
||||
if (__elems_after > __n)
|
||||
{
|
||||
std::__uninitialized_move_a(this->_M_impl._M_finish - __n,
|
||||
this->_M_impl._M_finish,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
this->_M_impl._M_finish += __n;
|
||||
_GLIBCXX_MOVE_BACKWARD3(__position.base(),
|
||||
__old_finish - __n, __old_finish);
|
||||
std::copy(__first, __last, __position);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ForwardIterator __mid = __first;
|
||||
std::advance(__mid, __elems_after);
|
||||
std::__uninitialized_copy_a(__mid, __last,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
this->_M_impl._M_finish += __n - __elems_after;
|
||||
std::__uninitialized_move_a(__position.base(),
|
||||
__old_finish,
|
||||
this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
this->_M_impl._M_finish += __elems_after;
|
||||
std::copy(__first, __mid, __position);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector::_M_range_insert");
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __new_finish(__new_start);
|
||||
__try
|
||||
{
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(this->_M_impl._M_start, __position.base(),
|
||||
__new_start, _M_get_Tp_allocator());
|
||||
__new_finish
|
||||
= std::__uninitialized_copy_a(__first, __last,
|
||||
__new_finish,
|
||||
_M_get_Tp_allocator());
|
||||
__new_finish
|
||||
= std::__uninitialized_move_if_noexcept_a
|
||||
(__position.base(), this->_M_impl._M_finish,
|
||||
__new_finish, _M_get_Tp_allocator());
|
||||
}
|
||||
__catch(...)
|
||||
{
|
||||
std::_Destroy(__new_start, __new_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(this->_M_impl._M_start,
|
||||
this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_start);
|
||||
this->_M_impl._M_start = __new_start;
|
||||
this->_M_impl._M_finish = __new_finish;
|
||||
this->_M_impl._M_end_of_storage = __new_start + __len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vector<bool>
|
||||
template<typename _Alloc>
|
||||
void
|
||||
vector<bool, _Alloc>::
|
||||
_M_reallocate(size_type __n)
|
||||
{
|
||||
_Bit_pointer __q = this->_M_allocate(__n);
|
||||
iterator __start(std::__addressof(*__q), 0);
|
||||
iterator __finish(_M_copy_aligned(begin(), end(), __start));
|
||||
this->_M_deallocate();
|
||||
this->_M_impl._M_start = __start;
|
||||
this->_M_impl._M_finish = __finish;
|
||||
this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
void
|
||||
vector<bool, _Alloc>::
|
||||
_M_fill_insert(iterator __position, size_type __n, bool __x)
|
||||
{
|
||||
if (__n == 0)
|
||||
return;
|
||||
if (capacity() - size() >= __n)
|
||||
{
|
||||
std::copy_backward(__position, end(),
|
||||
this->_M_impl._M_finish + difference_type(__n));
|
||||
std::fill(__position, __position + difference_type(__n), __x);
|
||||
this->_M_impl._M_finish += difference_type(__n);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector<bool>::_M_fill_insert");
|
||||
_Bit_pointer __q = this->_M_allocate(__len);
|
||||
iterator __start(std::__addressof(*__q), 0);
|
||||
iterator __i = _M_copy_aligned(begin(), __position, __start);
|
||||
std::fill(__i, __i + difference_type(__n), __x);
|
||||
iterator __finish = std::copy(__position, end(),
|
||||
__i + difference_type(__n));
|
||||
this->_M_deallocate();
|
||||
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
|
||||
this->_M_impl._M_start = __start;
|
||||
this->_M_impl._M_finish = __finish;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
template<typename _ForwardIterator>
|
||||
void
|
||||
vector<bool, _Alloc>::
|
||||
_M_insert_range(iterator __position, _ForwardIterator __first,
|
||||
_ForwardIterator __last, std::forward_iterator_tag)
|
||||
{
|
||||
if (__first != __last)
|
||||
{
|
||||
size_type __n = std::distance(__first, __last);
|
||||
if (capacity() - size() >= __n)
|
||||
{
|
||||
std::copy_backward(__position, end(),
|
||||
this->_M_impl._M_finish
|
||||
+ difference_type(__n));
|
||||
std::copy(__first, __last, __position);
|
||||
this->_M_impl._M_finish += difference_type(__n);
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector<bool>::_M_insert_range");
|
||||
_Bit_pointer __q = this->_M_allocate(__len);
|
||||
iterator __start(std::__addressof(*__q), 0);
|
||||
iterator __i = _M_copy_aligned(begin(), __position, __start);
|
||||
__i = std::copy(__first, __last, __i);
|
||||
iterator __finish = std::copy(__position, end(), __i);
|
||||
this->_M_deallocate();
|
||||
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
|
||||
this->_M_impl._M_start = __start;
|
||||
this->_M_impl._M_finish = __finish;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
void
|
||||
vector<bool, _Alloc>::
|
||||
_M_insert_aux(iterator __position, bool __x)
|
||||
{
|
||||
if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr())
|
||||
{
|
||||
std::copy_backward(__position, this->_M_impl._M_finish,
|
||||
this->_M_impl._M_finish + 1);
|
||||
*__position = __x;
|
||||
++this->_M_impl._M_finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_type __len =
|
||||
_M_check_len(size_type(1), "vector<bool>::_M_insert_aux");
|
||||
_Bit_pointer __q = this->_M_allocate(__len);
|
||||
iterator __start(std::__addressof(*__q), 0);
|
||||
iterator __i = _M_copy_aligned(begin(), __position, __start);
|
||||
*__i++ = __x;
|
||||
iterator __finish = std::copy(__position, end(), __i);
|
||||
this->_M_deallocate();
|
||||
this->_M_impl._M_end_of_storage = __q + _S_nword(__len);
|
||||
this->_M_impl._M_start = __start;
|
||||
this->_M_impl._M_finish = __finish;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
typename vector<bool, _Alloc>::iterator
|
||||
vector<bool, _Alloc>::
|
||||
_M_erase(iterator __position)
|
||||
{
|
||||
if (__position + 1 != end())
|
||||
std::copy(__position + 1, end(), __position);
|
||||
--this->_M_impl._M_finish;
|
||||
return __position;
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
typename vector<bool, _Alloc>::iterator
|
||||
vector<bool, _Alloc>::
|
||||
_M_erase(iterator __first, iterator __last)
|
||||
{
|
||||
if (__first != __last)
|
||||
_M_erase_at_end(std::copy(__last, end(), __first));
|
||||
return __first;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Alloc>
|
||||
bool
|
||||
vector<bool, _Alloc>::
|
||||
_M_shrink_to_fit()
|
||||
{
|
||||
if (capacity() - size() < int(_S_word_bit))
|
||||
return false;
|
||||
__try
|
||||
{
|
||||
_M_reallocate(size());
|
||||
return true;
|
||||
}
|
||||
__catch(...)
|
||||
{ return false; }
|
||||
}
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_CONTAINER
|
||||
} // namespace std
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _Alloc>
|
||||
size_t
|
||||
hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>::
|
||||
operator()(const _GLIBCXX_STD_C::vector<bool, _Alloc>& __b) const noexcept
|
||||
{
|
||||
size_t __hash = 0;
|
||||
using _GLIBCXX_STD_C::_S_word_bit;
|
||||
using _GLIBCXX_STD_C::_Bit_type;
|
||||
|
||||
const size_t __words = __b.size() / _S_word_bit;
|
||||
if (__words)
|
||||
{
|
||||
const size_t __clength = __words * sizeof(_Bit_type);
|
||||
__hash = std::_Hash_impl::hash(__b._M_impl._M_start._M_p, __clength);
|
||||
}
|
||||
|
||||
const size_t __extrabits = __b.size() % _S_word_bit;
|
||||
if (__extrabits)
|
||||
{
|
||||
_Bit_type __hiword = *__b._M_impl._M_finish._M_p;
|
||||
__hiword &= ~((~static_cast<_Bit_type>(0)) << __extrabits);
|
||||
|
||||
const size_t __clength
|
||||
= (__extrabits + __CHAR_BIT__ - 1) / __CHAR_BIT__;
|
||||
if (__words)
|
||||
__hash = std::_Hash_impl::hash(&__hiword, __clength, __hash);
|
||||
else
|
||||
__hash = std::_Hash_impl::hash(&__hiword, __clength);
|
||||
}
|
||||
|
||||
return __hash;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif /* _VECTOR_TCC */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,59 @@
|
|||
// -*- C++ -*- forwarding header.
|
||||
|
||||
// Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/climits
|
||||
* This is a Standard C++ Library file. You should @c \#include this file
|
||||
* in your programs, rather than any of the @a *.h implementation files.
|
||||
*
|
||||
* This is the C++ version of the Standard C Library header @c limits.h,
|
||||
* and its contents are (mostly) the same as that header, but are all
|
||||
* contained in the namespace @c std (except for names which are defined
|
||||
* as macros in C).
|
||||
*/
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 18.2.2 Implementation properties: C library
|
||||
//
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/c++config.h"
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef _GLIBCXX_CLIMITS
|
||||
#define _GLIBCXX_CLIMITS 1
|
||||
|
||||
#ifndef LLONG_MIN
|
||||
#define LLONG_MIN (-__LONG_LONG_MAX__ - 1)
|
||||
#endif
|
||||
|
||||
#ifndef LLONG_MAX
|
||||
#define LLONG_MAX __LONG_LONG_MAX__
|
||||
#endif
|
||||
|
||||
#ifndef ULLONG_MAX
|
||||
#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,191 @@
|
|||
// -*- C++ -*- forwarding header.
|
||||
|
||||
// Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file cstddef
|
||||
* This is a Standard C++ Library file. You should @c \#include this file
|
||||
* in your programs, rather than any of the @a *.h implementation files.
|
||||
*
|
||||
* This is the C++ version of the Standard C Library header @c stddef.h,
|
||||
* and its contents are (mostly) the same as that header, but are all
|
||||
* contained in the namespace @c std (except for names which are defined
|
||||
* as macros in C).
|
||||
*/
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 18.1 Types
|
||||
//
|
||||
|
||||
#ifndef _GLIBCXX_CSTDDEF
|
||||
#define _GLIBCXX_CSTDDEF 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#undef __need_wchar_t
|
||||
#undef __need_ptrdiff_t
|
||||
#undef __need_size_t
|
||||
#undef __need_NULL
|
||||
#undef __need_wint_t
|
||||
#include "bits/c++config.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
namespace std
|
||||
{
|
||||
// We handle size_t, ptrdiff_t, and nullptr_t in c++config.h.
|
||||
using ::max_align_t;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
namespace std
|
||||
{
|
||||
#define __cpp_lib_byte 201603
|
||||
|
||||
/// std::byte
|
||||
enum class byte : unsigned char {};
|
||||
|
||||
template<typename _IntegerType> struct __byte_operand { };
|
||||
template<> struct __byte_operand<bool> { using __type = byte; };
|
||||
template<> struct __byte_operand<char> { using __type = byte; };
|
||||
template<> struct __byte_operand<signed char> { using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned char> { using __type = byte; };
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template<> struct __byte_operand<wchar_t> { using __type = byte; };
|
||||
#endif
|
||||
template<> struct __byte_operand<char16_t> { using __type = byte; };
|
||||
template<> struct __byte_operand<char32_t> { using __type = byte; };
|
||||
template<> struct __byte_operand<short> { using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned short> { using __type = byte; };
|
||||
template<> struct __byte_operand<int> { using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned int> { using __type = byte; };
|
||||
template<> struct __byte_operand<long> { using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned long> { using __type = byte; };
|
||||
template<> struct __byte_operand<long long> { using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned long long> { using __type = byte; };
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_0)
|
||||
template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_0>
|
||||
{ using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned __GLIBCXX_TYPE_INT_N_0>
|
||||
{ using __type = byte; };
|
||||
#endif
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_1)
|
||||
template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_1>
|
||||
{ using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned __GLIBCXX_TYPE_INT_N_1>
|
||||
{ using __type = byte; };
|
||||
#endif
|
||||
#if defined(__GLIBCXX_TYPE_INT_N_2)
|
||||
template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_2>
|
||||
{ using __type = byte; };
|
||||
template<> struct __byte_operand<unsigned __GLIBCXX_TYPE_INT_N_2>
|
||||
{ using __type = byte; };
|
||||
#endif
|
||||
template<typename _IntegerType>
|
||||
struct __byte_operand<const _IntegerType>
|
||||
: __byte_operand<_IntegerType> { };
|
||||
template<typename _IntegerType>
|
||||
struct __byte_operand<volatile _IntegerType>
|
||||
: __byte_operand<_IntegerType> { };
|
||||
template<typename _IntegerType>
|
||||
struct __byte_operand<const volatile _IntegerType>
|
||||
: __byte_operand<_IntegerType> { };
|
||||
|
||||
template<typename _IntegerType>
|
||||
using __byte_op_t = typename __byte_operand<_IntegerType>::__type;
|
||||
|
||||
template<typename _IntegerType>
|
||||
constexpr __byte_op_t<_IntegerType>&
|
||||
operator<<=(byte& __b, _IntegerType __shift) noexcept
|
||||
{ return __b = byte(static_cast<unsigned char>(__b) << __shift); }
|
||||
|
||||
template<typename _IntegerType>
|
||||
constexpr __byte_op_t<_IntegerType>
|
||||
operator<<(byte __b, _IntegerType __shift) noexcept
|
||||
{ return byte(static_cast<unsigned char>(__b) << __shift); }
|
||||
|
||||
template<typename _IntegerType>
|
||||
constexpr __byte_op_t<_IntegerType>&
|
||||
operator>>=(byte& __b, _IntegerType __shift) noexcept
|
||||
{ return __b = byte(static_cast<unsigned char>(__b) >> __shift); }
|
||||
|
||||
template<typename _IntegerType>
|
||||
constexpr __byte_op_t<_IntegerType>
|
||||
operator>>(byte __b, _IntegerType __shift) noexcept
|
||||
{ return byte(static_cast<unsigned char>(__b) >> __shift); }
|
||||
|
||||
constexpr byte&
|
||||
operator|=(byte& __l, byte __r) noexcept
|
||||
{
|
||||
return __l =
|
||||
byte(static_cast<unsigned char>(__l) | static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte
|
||||
operator|(byte __l, byte __r) noexcept
|
||||
{
|
||||
return
|
||||
byte(static_cast<unsigned char>(__l) | static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte&
|
||||
operator&=(byte& __l, byte __r) noexcept
|
||||
{
|
||||
return __l =
|
||||
byte(static_cast<unsigned char>(__l) & static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte
|
||||
operator&(byte __l, byte __r) noexcept
|
||||
{
|
||||
return
|
||||
byte(static_cast<unsigned char>(__l) & static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte&
|
||||
operator^=(byte& __l, byte __r) noexcept
|
||||
{
|
||||
return __l =
|
||||
byte(static_cast<unsigned char>(__l) ^ static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte
|
||||
operator^(byte __l, byte __r) noexcept
|
||||
{
|
||||
return
|
||||
byte(static_cast<unsigned char>(__l) ^ static_cast<unsigned char>(__r));
|
||||
}
|
||||
|
||||
constexpr byte
|
||||
operator~(byte __b) noexcept
|
||||
{ return byte(~static_cast<unsigned char>(__b)); }
|
||||
|
||||
template<typename _IntegerType>
|
||||
constexpr _IntegerType
|
||||
to_integer(__byte_op_t<_IntegerType> __b) noexcept
|
||||
{ return _IntegerType(__b); }
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#endif // _GLIBCXX_CSTDDEF
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// <cstdint> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/cstdint
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_CSTDINT
|
||||
#define _GLIBCXX_CSTDINT 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include "bits/c++0x_warning.h"
|
||||
#else
|
||||
|
||||
#include "bits/c++config.h"
|
||||
|
||||
#if _GLIBCXX_HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_USE_C99_STDINT_TR1
|
||||
|
||||
namespace std
|
||||
{
|
||||
using ::int8_t;
|
||||
using ::int16_t;
|
||||
using ::int32_t;
|
||||
using ::int64_t;
|
||||
|
||||
using ::int_fast8_t;
|
||||
using ::int_fast16_t;
|
||||
using ::int_fast32_t;
|
||||
using ::int_fast64_t;
|
||||
|
||||
using ::int_least8_t;
|
||||
using ::int_least16_t;
|
||||
using ::int_least32_t;
|
||||
using ::int_least64_t;
|
||||
|
||||
using ::intmax_t;
|
||||
using ::intptr_t;
|
||||
|
||||
using ::uint8_t;
|
||||
using ::uint16_t;
|
||||
using ::uint32_t;
|
||||
using ::uint64_t;
|
||||
|
||||
using ::uint_fast8_t;
|
||||
using ::uint_fast16_t;
|
||||
using ::uint_fast32_t;
|
||||
using ::uint_fast64_t;
|
||||
|
||||
using ::uint_least8_t;
|
||||
using ::uint_least16_t;
|
||||
using ::uint_least32_t;
|
||||
using ::uint_least64_t;
|
||||
|
||||
using ::uintmax_t;
|
||||
using ::uintptr_t;
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_USE_C99_STDINT_TR1
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _GLIBCXX_CSTDINT
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
// -*- C++ -*- forwarding header.
|
||||
|
||||
// Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file include/cstdlib
|
||||
* This is a Standard C++ Library file. You should @c \#include this file
|
||||
* in your programs, rather than any of the @a *.h implementation files.
|
||||
*
|
||||
* This is the C++ version of the Standard C Library header @c stdlib.h,
|
||||
* and its contents are (mostly) the same as that header, but are all
|
||||
* contained in the namespace @c std (except for names which are defined
|
||||
* as macros in C).
|
||||
*/
|
||||
|
||||
//
|
||||
// ISO C++ 14882: 20.4.6 C library
|
||||
//
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/c++config.h"
|
||||
|
||||
#ifndef _GLIBCXX_CSTDLIB
|
||||
#define _GLIBCXX_CSTDLIB 1
|
||||
|
||||
#if !_GLIBCXX_HOSTED
|
||||
// The C standard does not require a freestanding implementation to
|
||||
// provide <stdlib.h>. However, the C++ standard does still require
|
||||
// <cstdlib> -- but only the functionality mentioned in
|
||||
// [lib.support.start.term].
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
|
||||
namespace std
|
||||
{
|
||||
extern "C" void abort(void) throw () _GLIBCXX_NORETURN;
|
||||
extern "C" int atexit(void (*)(void)) throw ();
|
||||
extern "C" void exit(int) throw () _GLIBCXX_NORETURN;
|
||||
#if __cplusplus >= 201103L
|
||||
# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT
|
||||
extern "C" int at_quick_exit(void (*)(void)) throw ();
|
||||
# endif
|
||||
# ifdef _GLIBCXX_HAVE_QUICK_EXIT
|
||||
extern "C" void quick_exit(int) throw() _GLIBCXX_NORETURN;
|
||||
# endif
|
||||
#endif
|
||||
} // namespace std
|
||||
|
||||
#else
|
||||
|
||||
// Need to ensure this finds the C library's <stdlib.h> not a libstdc++
|
||||
// wrapper that might already be installed later in the include search path.
|
||||
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
#include_next <stdlib.h>
|
||||
#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
#include "bits/std_abs.h"
|
||||
|
||||
// Get rid of those macros defined in <stdlib.h> in lieu of real functions.
|
||||
#undef abort
|
||||
#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)
|
||||
# undef aligned_alloc
|
||||
#endif
|
||||
#undef atexit
|
||||
#if __cplusplus >= 201103L
|
||||
# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT
|
||||
# undef at_quick_exit
|
||||
# endif
|
||||
#endif
|
||||
#undef atof
|
||||
#undef atoi
|
||||
#undef atol
|
||||
#undef bsearch
|
||||
#undef calloc
|
||||
#undef div
|
||||
#undef exit
|
||||
#undef free
|
||||
#undef getenv
|
||||
#undef labs
|
||||
#undef ldiv
|
||||
#undef malloc
|
||||
#undef mblen
|
||||
#undef mbstowcs
|
||||
#undef mbtowc
|
||||
#undef qsort
|
||||
#if __cplusplus >= 201103L
|
||||
# ifdef _GLIBCXX_HAVE_QUICK_EXIT
|
||||
# undef quick_exit
|
||||
# endif
|
||||
#endif
|
||||
#undef rand
|
||||
#undef realloc
|
||||
#undef srand
|
||||
#undef strtod
|
||||
#undef strtol
|
||||
#undef strtoul
|
||||
#undef system
|
||||
#undef wcstombs
|
||||
#undef wctomb
|
||||
|
||||
extern "C++"
|
||||
{
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
using ::div_t;
|
||||
using ::ldiv_t;
|
||||
|
||||
using ::abort;
|
||||
#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)
|
||||
using ::aligned_alloc;
|
||||
#endif
|
||||
using ::atexit;
|
||||
#if __cplusplus >= 201103L
|
||||
# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT
|
||||
using ::at_quick_exit;
|
||||
# endif
|
||||
#endif
|
||||
using ::atof;
|
||||
using ::atoi;
|
||||
using ::atol;
|
||||
using ::bsearch;
|
||||
using ::calloc;
|
||||
using ::div;
|
||||
using ::exit;
|
||||
using ::free;
|
||||
using ::getenv;
|
||||
using ::labs;
|
||||
using ::ldiv;
|
||||
using ::malloc;
|
||||
#ifdef _GLIBCXX_HAVE_MBSTATE_T
|
||||
using ::mblen;
|
||||
using ::mbstowcs;
|
||||
using ::mbtowc;
|
||||
#endif // _GLIBCXX_HAVE_MBSTATE_T
|
||||
using ::qsort;
|
||||
#if __cplusplus >= 201103L
|
||||
# ifdef _GLIBCXX_HAVE_QUICK_EXIT
|
||||
using ::quick_exit;
|
||||
# endif
|
||||
#endif
|
||||
using ::rand;
|
||||
using ::realloc;
|
||||
using ::srand;
|
||||
using ::strtod;
|
||||
using ::strtol;
|
||||
using ::strtoul;
|
||||
using ::system;
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
using ::wcstombs;
|
||||
using ::wctomb;
|
||||
#endif // _GLIBCXX_USE_WCHAR_T
|
||||
|
||||
#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO
|
||||
inline ldiv_t
|
||||
div(long __i, long __j) { return ldiv(__i, __j); }
|
||||
#endif
|
||||
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#if _GLIBCXX_USE_C99_STDLIB
|
||||
|
||||
#undef _Exit
|
||||
#undef llabs
|
||||
#undef lldiv
|
||||
#undef atoll
|
||||
#undef strtoll
|
||||
#undef strtoull
|
||||
#undef strtof
|
||||
#undef strtold
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
using ::lldiv_t;
|
||||
#endif
|
||||
#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC
|
||||
extern "C" void (_Exit)(int) throw () _GLIBCXX_NORETURN;
|
||||
#endif
|
||||
#if !_GLIBCXX_USE_C99_DYNAMIC
|
||||
using ::_Exit;
|
||||
#endif
|
||||
|
||||
#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
using ::llabs;
|
||||
|
||||
inline lldiv_t
|
||||
div(long long __n, long long __d)
|
||||
{ lldiv_t __q; __q.quot = __n / __d; __q.rem = __n % __d; return __q; }
|
||||
|
||||
using ::lldiv;
|
||||
#endif
|
||||
|
||||
#if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
extern "C" long long int (atoll)(const char *) throw ();
|
||||
extern "C" long long int
|
||||
(strtoll)(const char * __restrict, char ** __restrict, int) throw ();
|
||||
extern "C" unsigned long long int
|
||||
(strtoull)(const char * __restrict, char ** __restrict, int) throw ();
|
||||
#endif
|
||||
#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
using ::atoll;
|
||||
using ::strtoll;
|
||||
using ::strtoull;
|
||||
#endif
|
||||
|
||||
#ifdef AH_USE_STRTOF
|
||||
using ::strtof;
|
||||
using ::strtold;
|
||||
#endif
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace __gnu_cxx
|
||||
|
||||
namespace std
|
||||
{
|
||||
#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
using ::__gnu_cxx::lldiv_t;
|
||||
#endif
|
||||
using ::__gnu_cxx::_Exit;
|
||||
#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
|
||||
using ::__gnu_cxx::llabs;
|
||||
using ::__gnu_cxx::div;
|
||||
using ::__gnu_cxx::lldiv;
|
||||
#endif
|
||||
using ::__gnu_cxx::atoll;
|
||||
#ifdef AH_USE_STRTOF
|
||||
using ::__gnu_cxx::strtof;
|
||||
#endif
|
||||
using ::__gnu_cxx::strtoll;
|
||||
using ::__gnu_cxx::strtoull;
|
||||
#ifdef AH_USE_STRTOF
|
||||
using ::__gnu_cxx::strtold;
|
||||
#endif
|
||||
} // namespace std
|
||||
|
||||
#endif // _GLIBCXX_USE_C99_STDLIB
|
||||
|
||||
} // extern "C++"
|
||||
|
||||
#endif // !_GLIBCXX_HOSTED
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Debugging support implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2003-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file debug/assertions.h
|
||||
* This file is a GNU debug extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H
|
||||
#define _GLIBCXX_DEBUG_ASSERTIONS_H 1
|
||||
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
|
||||
# define _GLIBCXX_DEBUG_ASSERT(_Condition)
|
||||
# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
|
||||
# define _GLIBCXX_DEBUG_ONLY(_Statement)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_ASSERTIONS
|
||||
# define __glibcxx_requires_non_empty_range(_First,_Last)
|
||||
# define __glibcxx_requires_nonempty()
|
||||
# define __glibcxx_requires_subscript(_N)
|
||||
#else
|
||||
|
||||
// Verify that [_First, _Last) forms a non-empty iterator range.
|
||||
# define __glibcxx_requires_non_empty_range(_First,_Last) \
|
||||
__glibcxx_assert(__builtin_expect(_First != _Last, true))
|
||||
# define __glibcxx_requires_subscript(_N) \
|
||||
__glibcxx_assert(__builtin_expect(_N < this->size(), true))
|
||||
// Verify that the container is nonempty
|
||||
# define __glibcxx_requires_nonempty() \
|
||||
__glibcxx_assert(__builtin_expect(!this->empty(), true))
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_DEBUG
|
||||
# define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition)
|
||||
|
||||
# ifdef _GLIBCXX_DEBUG_PEDANTIC
|
||||
# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition)
|
||||
# else
|
||||
# define _GLIBCXX_DEBUG_PEDASSERT(_Condition)
|
||||
# endif
|
||||
|
||||
# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement
|
||||
#endif
|
||||
|
||||
#endif // _GLIBCXX_DEBUG_ASSERTIONS
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// Debugging support implementation -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2003-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file debug/debug.h
|
||||
* This file is a GNU debug extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H
|
||||
#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1
|
||||
|
||||
/** Macros and namespaces used by the implementation outside of debug
|
||||
* wrappers to verify certain properties. The __glibcxx_requires_xxx
|
||||
* macros are merely wrappers around the __glibcxx_check_xxx wrappers
|
||||
* when we are compiling with debug mode, but disappear when we are
|
||||
* in release mode so that there is no checking performed in, e.g.,
|
||||
* the standard library algorithms.
|
||||
*/
|
||||
|
||||
#include "../debug/assertions.h"
|
||||
|
||||
// Debug mode namespaces.
|
||||
|
||||
/**
|
||||
* @namespace std::__debug
|
||||
* @brief GNU debug code, replaces standard behavior with debug behavior.
|
||||
*/
|
||||
namespace std
|
||||
{
|
||||
namespace __debug { }
|
||||
}
|
||||
|
||||
/** @namespace __gnu_debug
|
||||
* @brief GNU debug classes for public use.
|
||||
*/
|
||||
namespace __gnu_debug
|
||||
{
|
||||
using namespace std::__debug;
|
||||
}
|
||||
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
|
||||
# define __glibcxx_requires_cond(_Cond,_Msg)
|
||||
# define __glibcxx_requires_valid_range(_First,_Last)
|
||||
# define __glibcxx_requires_sorted(_First,_Last)
|
||||
# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2)
|
||||
# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred)
|
||||
# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value)
|
||||
# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value)
|
||||
# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred)
|
||||
# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred)
|
||||
# define __glibcxx_requires_heap(_First,_Last)
|
||||
# define __glibcxx_requires_heap_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_string(_String)
|
||||
# define __glibcxx_requires_string_len(_String,_Len)
|
||||
# define __glibcxx_requires_irreflexive(_First,_Last)
|
||||
# define __glibcxx_requires_irreflexive2(_First,_Last)
|
||||
# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred)
|
||||
|
||||
#else
|
||||
|
||||
# include <debug/macros.h>
|
||||
|
||||
# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg)
|
||||
# define __glibcxx_requires_valid_range(_First,_Last) \
|
||||
__glibcxx_check_valid_range(_First,_Last)
|
||||
# define __glibcxx_requires_sorted(_First,_Last) \
|
||||
__glibcxx_check_sorted(_First,_Last)
|
||||
# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \
|
||||
__glibcxx_check_sorted_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \
|
||||
__glibcxx_check_sorted_set(_First1,_Last1,_First2)
|
||||
# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \
|
||||
__glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred)
|
||||
# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \
|
||||
__glibcxx_check_partitioned_lower(_First,_Last,_Value)
|
||||
# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \
|
||||
__glibcxx_check_partitioned_upper(_First,_Last,_Value)
|
||||
# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \
|
||||
__glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred)
|
||||
# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \
|
||||
__glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred)
|
||||
# define __glibcxx_requires_heap(_First,_Last) \
|
||||
__glibcxx_check_heap(_First,_Last)
|
||||
# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \
|
||||
__glibcxx_check_heap_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_string(_String) __glibcxx_check_string(_String)
|
||||
# define __glibcxx_requires_string_len(_String,_Len) \
|
||||
__glibcxx_check_string_len(_String,_Len)
|
||||
# define __glibcxx_requires_irreflexive(_First,_Last) \
|
||||
__glibcxx_check_irreflexive(_First,_Last)
|
||||
# define __glibcxx_requires_irreflexive2(_First,_Last) \
|
||||
__glibcxx_check_irreflexive2(_First,_Last)
|
||||
# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) \
|
||||
__glibcxx_check_irreflexive_pred(_First,_Last,_Pred)
|
||||
# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) \
|
||||
__glibcxx_check_irreflexive_pred2(_First,_Last,_Pred)
|
||||
|
||||
# include <debug/functions.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// Allocator traits -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file ext/alloc_traits.h
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _EXT_ALLOC_TRAITS_H
|
||||
#define _EXT_ALLOC_TRAITS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
# include "../bits/move.h"
|
||||
# include "../bits/alloc_traits.h"
|
||||
#else
|
||||
# include "../bits/allocator.h" // for __alloc_swap
|
||||
#endif
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief Uniform interface to C++98 and C++11 allocators.
|
||||
* @ingroup allocators
|
||||
*/
|
||||
template<typename _Alloc>
|
||||
struct __alloc_traits
|
||||
#if __cplusplus >= 201103L
|
||||
: std::allocator_traits<_Alloc>
|
||||
#endif
|
||||
{
|
||||
typedef _Alloc allocator_type;
|
||||
#if __cplusplus >= 201103L
|
||||
typedef std::allocator_traits<_Alloc> _Base_type;
|
||||
typedef typename _Base_type::value_type value_type;
|
||||
typedef typename _Base_type::pointer pointer;
|
||||
typedef typename _Base_type::const_pointer const_pointer;
|
||||
typedef typename _Base_type::size_type size_type;
|
||||
typedef typename _Base_type::difference_type difference_type;
|
||||
// C++11 allocators do not define reference or const_reference
|
||||
typedef value_type& reference;
|
||||
typedef const value_type& const_reference;
|
||||
using _Base_type::allocate;
|
||||
using _Base_type::deallocate;
|
||||
using _Base_type::construct;
|
||||
using _Base_type::destroy;
|
||||
using _Base_type::max_size;
|
||||
|
||||
private:
|
||||
template<typename _Ptr>
|
||||
using __is_custom_pointer
|
||||
= std::__and_<std::is_same<pointer, _Ptr>,
|
||||
std::__not_<std::is_pointer<_Ptr>>>;
|
||||
|
||||
public:
|
||||
// overload construct for non-standard pointer types
|
||||
template<typename _Ptr, typename... _Args>
|
||||
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
|
||||
construct(_Alloc& __a, _Ptr __p, _Args&&... __args)
|
||||
{
|
||||
_Base_type::construct(__a, std::addressof(*__p),
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// overload destroy for non-standard pointer types
|
||||
template<typename _Ptr>
|
||||
static typename std::enable_if<__is_custom_pointer<_Ptr>::value>::type
|
||||
destroy(_Alloc& __a, _Ptr __p)
|
||||
{ _Base_type::destroy(__a, std::addressof(*__p)); }
|
||||
|
||||
static _Alloc _S_select_on_copy(const _Alloc& __a)
|
||||
{ return _Base_type::select_on_container_copy_construction(__a); }
|
||||
|
||||
static void _S_on_swap(_Alloc& __a, _Alloc& __b)
|
||||
{ std::__alloc_on_swap(__a, __b); }
|
||||
|
||||
static constexpr bool _S_propagate_on_copy_assign()
|
||||
{ return _Base_type::propagate_on_container_copy_assignment::value; }
|
||||
|
||||
static constexpr bool _S_propagate_on_move_assign()
|
||||
{ return _Base_type::propagate_on_container_move_assignment::value; }
|
||||
|
||||
static constexpr bool _S_propagate_on_swap()
|
||||
{ return _Base_type::propagate_on_container_swap::value; }
|
||||
|
||||
static constexpr bool _S_always_equal()
|
||||
{ return _Base_type::is_always_equal::value; }
|
||||
|
||||
static constexpr bool _S_nothrow_move()
|
||||
{ return _S_propagate_on_move_assign() || _S_always_equal(); }
|
||||
|
||||
template<typename _Tp>
|
||||
struct rebind
|
||||
{ typedef typename _Base_type::template rebind_alloc<_Tp> other; };
|
||||
#else
|
||||
|
||||
typedef typename _Alloc::pointer pointer;
|
||||
typedef typename _Alloc::const_pointer const_pointer;
|
||||
typedef typename _Alloc::value_type value_type;
|
||||
typedef typename _Alloc::reference reference;
|
||||
typedef typename _Alloc::const_reference const_reference;
|
||||
typedef typename _Alloc::size_type size_type;
|
||||
typedef typename _Alloc::difference_type difference_type;
|
||||
|
||||
static pointer
|
||||
allocate(_Alloc& __a, size_type __n)
|
||||
{ return __a.allocate(__n); }
|
||||
|
||||
static void deallocate(_Alloc& __a, pointer __p, size_type __n)
|
||||
{ __a.deallocate(__p, __n); }
|
||||
|
||||
template<typename _Tp>
|
||||
static void construct(_Alloc& __a, pointer __p, const _Tp& __arg)
|
||||
{ __a.construct(__p, __arg); }
|
||||
|
||||
static void destroy(_Alloc& __a, pointer __p)
|
||||
{ __a.destroy(__p); }
|
||||
|
||||
static size_type max_size(const _Alloc& __a)
|
||||
{ return __a.max_size(); }
|
||||
|
||||
static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; }
|
||||
|
||||
static void _S_on_swap(_Alloc& __a, _Alloc& __b)
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 431. Swapping containers with unequal allocators.
|
||||
std::__alloc_swap<_Alloc>::_S_do_it(__a, __b);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
struct rebind
|
||||
{ typedef typename _Alloc::template rebind<_Tp>::other other; };
|
||||
#endif
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace __gnu_cxx
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
// Allocator that wraps operator new -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file ext/new_allocator.h
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _NEW_ALLOCATOR_H
|
||||
#define _NEW_ALLOCATOR_H 1
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../new"
|
||||
#include "../bits/functexcept.h"
|
||||
#include "../bits/move.h"
|
||||
#if __cplusplus >= 201103L
|
||||
#include "../type_traits"
|
||||
#endif
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
using std::size_t;
|
||||
using std::ptrdiff_t;
|
||||
|
||||
/**
|
||||
* @brief An allocator that uses global new, as per [20.4].
|
||||
* @ingroup allocators
|
||||
*
|
||||
* This is precisely the allocator defined in the C++ Standard.
|
||||
* - all allocation calls operator new
|
||||
* - all deallocation calls operator delete
|
||||
*
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class new_allocator
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef _Tp* pointer;
|
||||
typedef const _Tp* const_pointer;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
typedef _Tp value_type;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef new_allocator<_Tp1> other; };
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. propagate_on_container_move_assignment
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
#endif
|
||||
|
||||
new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
template<typename _Tp1>
|
||||
new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
pointer
|
||||
address(reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
|
||||
const_pointer
|
||||
address(const_reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
|
||||
// NB: __n is permitted to be 0. The C++ standard says nothing
|
||||
// about what the return value is when __n == 0.
|
||||
pointer
|
||||
allocate(size_type __n, const void* = static_cast<const void*>(0))
|
||||
{
|
||||
if (__n > this->max_size())
|
||||
__throw_bad_alloc();
|
||||
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
std::align_val_t __al = std::align_val_t(alignof(_Tp));
|
||||
_Tp* __newres = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
|
||||
if (__newres == nullptr)
|
||||
__throw_bad_alloc();
|
||||
return __newres;
|
||||
}
|
||||
#endif
|
||||
_Tp* __newres = static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
|
||||
if (__newres == nullptr)
|
||||
__throw_bad_alloc();
|
||||
return __newres;
|
||||
}
|
||||
|
||||
// __p is not permitted to be a null pointer.
|
||||
void
|
||||
deallocate(pointer __p, size_type)
|
||||
{
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
::operator delete(__p, std::align_val_t(alignof(_Tp)));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
::operator delete(__p);
|
||||
}
|
||||
|
||||
size_type
|
||||
max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{ return size_t(-1) / sizeof(_Tp); }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Up, typename... _Args>
|
||||
void
|
||||
construct(_Up* __p, _Args&&... __args)
|
||||
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
destroy(_Up* __p) { __p->~_Up(); }
|
||||
#else
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 402. wrong new expression in [some_] allocator::construct
|
||||
void
|
||||
construct(pointer __p, const _Tp& __val)
|
||||
{ ::new((void *)__p) _Tp(__val); }
|
||||
|
||||
void
|
||||
destroy(pointer __p) { __p->~_Tp(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
inline bool
|
||||
operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
|
||||
{ return true; }
|
||||
|
||||
template<typename _Tp>
|
||||
inline bool
|
||||
operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
|
||||
{ return false; }
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2007-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the terms
|
||||
// of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file ext/numeric_traits.h
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _EXT_NUMERIC_TRAITS
|
||||
#define _EXT_NUMERIC_TRAITS 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/cpp_type_traits.h"
|
||||
#include "../ext/type_traits.h"
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Compile time constants for builtin types.
|
||||
// Sadly std::numeric_limits member functions cannot be used for this.
|
||||
#define __glibcxx_signed(_Tp) ((_Tp)(-1) < 0)
|
||||
#define __glibcxx_digits(_Tp) \
|
||||
(sizeof(_Tp) * __CHAR_BIT__ - __glibcxx_signed(_Tp))
|
||||
|
||||
#define __glibcxx_min(_Tp) \
|
||||
(__glibcxx_signed(_Tp) ? (_Tp)1 << __glibcxx_digits(_Tp) : (_Tp)0)
|
||||
|
||||
#define __glibcxx_max(_Tp) \
|
||||
(__glibcxx_signed(_Tp) ? \
|
||||
(((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0)
|
||||
|
||||
template<typename _Value>
|
||||
struct __numeric_traits_integer
|
||||
{
|
||||
// Only integers for initialization of member constant.
|
||||
static const _Value __min = __glibcxx_min(_Value);
|
||||
static const _Value __max = __glibcxx_max(_Value);
|
||||
|
||||
// NB: these two also available in std::numeric_limits as compile
|
||||
// time constants, but <limits> is big and we avoid including it.
|
||||
static const bool __is_signed = __glibcxx_signed(_Value);
|
||||
static const int __digits = __glibcxx_digits(_Value);
|
||||
};
|
||||
|
||||
template<typename _Value>
|
||||
const _Value __numeric_traits_integer<_Value>::__min;
|
||||
|
||||
template<typename _Value>
|
||||
const _Value __numeric_traits_integer<_Value>::__max;
|
||||
|
||||
template<typename _Value>
|
||||
const bool __numeric_traits_integer<_Value>::__is_signed;
|
||||
|
||||
template<typename _Value>
|
||||
const int __numeric_traits_integer<_Value>::__digits;
|
||||
|
||||
#undef __glibcxx_signed
|
||||
#undef __glibcxx_digits
|
||||
#undef __glibcxx_min
|
||||
#undef __glibcxx_max
|
||||
|
||||
#define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \
|
||||
(std::__are_same<_Tp, float>::__value ? _Fval \
|
||||
: std::__are_same<_Tp, double>::__value ? _Dval : _LDval)
|
||||
|
||||
#define __glibcxx_max_digits10(_Tp) \
|
||||
(2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \
|
||||
__LDBL_MANT_DIG__) * 643L / 2136)
|
||||
|
||||
#define __glibcxx_digits10(_Tp) \
|
||||
__glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__)
|
||||
|
||||
#define __glibcxx_max_exponent10(_Tp) \
|
||||
__glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \
|
||||
__LDBL_MAX_10_EXP__)
|
||||
|
||||
template<typename _Value>
|
||||
struct __numeric_traits_floating
|
||||
{
|
||||
// Only floating point types. See N1822.
|
||||
static const int __max_digits10 = __glibcxx_max_digits10(_Value);
|
||||
|
||||
// See above comment...
|
||||
static const bool __is_signed = true;
|
||||
static const int __digits10 = __glibcxx_digits10(_Value);
|
||||
static const int __max_exponent10 = __glibcxx_max_exponent10(_Value);
|
||||
};
|
||||
|
||||
template<typename _Value>
|
||||
const int __numeric_traits_floating<_Value>::__max_digits10;
|
||||
|
||||
template<typename _Value>
|
||||
const bool __numeric_traits_floating<_Value>::__is_signed;
|
||||
|
||||
template<typename _Value>
|
||||
const int __numeric_traits_floating<_Value>::__digits10;
|
||||
|
||||
template<typename _Value>
|
||||
const int __numeric_traits_floating<_Value>::__max_exponent10;
|
||||
|
||||
template<typename _Value>
|
||||
struct __numeric_traits
|
||||
: public __conditional_type<std::__is_integer<_Value>::__value,
|
||||
__numeric_traits_integer<_Value>,
|
||||
__numeric_traits_floating<_Value> >::__type
|
||||
{ };
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#undef __glibcxx_floating
|
||||
#undef __glibcxx_max_digits10
|
||||
#undef __glibcxx_digits10
|
||||
#undef __glibcxx_max_exponent10
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
// -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2005-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the terms
|
||||
// of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file ext/type_traits.h
|
||||
* This file is a GNU extension to the Standard C++ Library.
|
||||
*/
|
||||
|
||||
#ifndef _EXT_TYPE_TRAITS
|
||||
#define _EXT_TYPE_TRAITS 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "../bits/c++config.h"
|
||||
#include "../bits/cpp_type_traits.h"
|
||||
|
||||
extern "C++" {
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// Define a nested type if some predicate holds.
|
||||
template<bool, typename>
|
||||
struct __enable_if
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __enable_if<true, _Tp>
|
||||
{ typedef _Tp __type; };
|
||||
|
||||
|
||||
// Conditional expression for types. If true, first, if false, second.
|
||||
template<bool _Cond, typename _Iftrue, typename _Iffalse>
|
||||
struct __conditional_type
|
||||
{ typedef _Iftrue __type; };
|
||||
|
||||
template<typename _Iftrue, typename _Iffalse>
|
||||
struct __conditional_type<false, _Iftrue, _Iffalse>
|
||||
{ typedef _Iffalse __type; };
|
||||
|
||||
|
||||
// Given an integral builtin type, return the corresponding unsigned type.
|
||||
template<typename _Tp>
|
||||
struct __add_unsigned
|
||||
{
|
||||
private:
|
||||
typedef __enable_if<std::__is_integer<_Tp>::__value, _Tp> __if_type;
|
||||
|
||||
public:
|
||||
typedef typename __if_type::__type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<char>
|
||||
{ typedef unsigned char __type; };
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<signed char>
|
||||
{ typedef unsigned char __type; };
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<short>
|
||||
{ typedef unsigned short __type; };
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<int>
|
||||
{ typedef unsigned int __type; };
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<long>
|
||||
{ typedef unsigned long __type; };
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<long long>
|
||||
{ typedef unsigned long long __type; };
|
||||
|
||||
// Declare but don't define.
|
||||
template<>
|
||||
struct __add_unsigned<bool>;
|
||||
|
||||
template<>
|
||||
struct __add_unsigned<wchar_t>;
|
||||
|
||||
|
||||
// Given an integral builtin type, return the corresponding signed type.
|
||||
template<typename _Tp>
|
||||
struct __remove_unsigned
|
||||
{
|
||||
private:
|
||||
typedef __enable_if<std::__is_integer<_Tp>::__value, _Tp> __if_type;
|
||||
|
||||
public:
|
||||
typedef typename __if_type::__type __type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<char>
|
||||
{ typedef signed char __type; };
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<unsigned char>
|
||||
{ typedef signed char __type; };
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<unsigned short>
|
||||
{ typedef short __type; };
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<unsigned int>
|
||||
{ typedef int __type; };
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<unsigned long>
|
||||
{ typedef long __type; };
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<unsigned long long>
|
||||
{ typedef long long __type; };
|
||||
|
||||
// Declare but don't define.
|
||||
template<>
|
||||
struct __remove_unsigned<bool>;
|
||||
|
||||
template<>
|
||||
struct __remove_unsigned<wchar_t>;
|
||||
|
||||
|
||||
// For use in string and vstring.
|
||||
template<typename _Type>
|
||||
inline bool
|
||||
__is_null_pointer(_Type* __ptr)
|
||||
{ return __ptr == 0; }
|
||||
|
||||
template<typename _Type>
|
||||
inline bool
|
||||
__is_null_pointer(_Type)
|
||||
{ return false; }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
inline bool
|
||||
__is_null_pointer(std::nullptr_t)
|
||||
{ return true; }
|
||||
#endif
|
||||
|
||||
// For complex and cmath
|
||||
template<typename _Tp, bool = std::__is_integer<_Tp>::__value>
|
||||
struct __promote
|
||||
{ typedef double __type; };
|
||||
|
||||
// No nested __type member for non-integer non-floating point types,
|
||||
// allows this type to be used for SFINAE to constrain overloads in
|
||||
// <cmath> and <complex> to only the intended types.
|
||||
template<typename _Tp>
|
||||
struct __promote<_Tp, false>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct __promote<long double>
|
||||
{ typedef long double __type; };
|
||||
|
||||
template<>
|
||||
struct __promote<double>
|
||||
{ typedef double __type; };
|
||||
|
||||
template<>
|
||||
struct __promote<float>
|
||||
{ typedef float __type; };
|
||||
|
||||
template<typename _Tp, typename _Up,
|
||||
typename _Tp2 = typename __promote<_Tp>::__type,
|
||||
typename _Up2 = typename __promote<_Up>::__type>
|
||||
struct __promote_2
|
||||
{
|
||||
typedef __typeof__(_Tp2() + _Up2()) __type;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up, typename _Vp,
|
||||
typename _Tp2 = typename __promote<_Tp>::__type,
|
||||
typename _Up2 = typename __promote<_Up>::__type,
|
||||
typename _Vp2 = typename __promote<_Vp>::__type>
|
||||
struct __promote_3
|
||||
{
|
||||
typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up, typename _Vp, typename _Wp,
|
||||
typename _Tp2 = typename __promote<_Tp>::__type,
|
||||
typename _Up2 = typename __promote<_Up>::__type,
|
||||
typename _Vp2 = typename __promote<_Vp>::__type,
|
||||
typename _Wp2 = typename __promote<_Wp>::__type>
|
||||
struct __promote_4
|
||||
{
|
||||
typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type;
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
} // extern "C++"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
// std::initializer_list support -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2008-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of GCC.
|
||||
//
|
||||
// GCC is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// GCC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file initializer_list
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _INITIALIZER_LIST
|
||||
#define _INITIALIZER_LIST
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
# include "bits/c++0x_warning.h"
|
||||
#else // C++0x
|
||||
|
||||
#pragma GCC visibility push(default)
|
||||
|
||||
#include "bits/c++config.h"
|
||||
|
||||
namespace std
|
||||
{
|
||||
/// initializer_list
|
||||
template<class _E>
|
||||
class initializer_list
|
||||
{
|
||||
public:
|
||||
typedef _E value_type;
|
||||
typedef const _E& reference;
|
||||
typedef const _E& const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef const _E* iterator;
|
||||
typedef const _E* const_iterator;
|
||||
|
||||
private:
|
||||
iterator _M_array;
|
||||
size_type _M_len;
|
||||
|
||||
// The compiler can call a private constructor.
|
||||
constexpr initializer_list(const_iterator __a, size_type __l)
|
||||
: _M_array(__a), _M_len(__l) { }
|
||||
|
||||
public:
|
||||
constexpr initializer_list() noexcept
|
||||
: _M_array(0), _M_len(0) { }
|
||||
|
||||
// Number of elements.
|
||||
constexpr size_type
|
||||
size() const noexcept { return _M_len; }
|
||||
|
||||
// First element.
|
||||
constexpr const_iterator
|
||||
begin() const noexcept { return _M_array; }
|
||||
|
||||
// One past the last element.
|
||||
constexpr const_iterator
|
||||
end() const noexcept { return begin() + size(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to the first element of
|
||||
* the initializer_list.
|
||||
* @param __ils Initializer list.
|
||||
*/
|
||||
template<class _Tp>
|
||||
constexpr const _Tp*
|
||||
begin(initializer_list<_Tp> __ils) noexcept
|
||||
{ return __ils.begin(); }
|
||||
|
||||
/**
|
||||
* @brief Return an iterator pointing to one past the last element
|
||||
* of the initializer_list.
|
||||
* @param __ils Initializer list.
|
||||
*/
|
||||
template<class _Tp>
|
||||
constexpr const _Tp*
|
||||
end(initializer_list<_Tp> __ils) noexcept
|
||||
{ return __ils.end(); }
|
||||
}
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
||||
#endif // C++11
|
||||
|
||||
#endif // _INITIALIZER_LIST
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// <iterator> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file include/iterator
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_ITERATOR
|
||||
#define _GLIBCXX_ITERATOR 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/c++config.h"
|
||||
#include "bits/stl_iterator_base_types.h"
|
||||
#include "bits/stl_iterator_base_funcs.h"
|
||||
#include "bits/stl_iterator.h"
|
||||
// #include <ostream>
|
||||
// #include <istream>
|
||||
// #include <bits/stream_iterator.h>
|
||||
// #include <bits/streambuf_iterator.h>
|
||||
#include "bits/range_access.h"
|
||||
|
||||
#endif /* _GLIBCXX_ITERATOR */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _GLIBCXX_MEMORY
|
||||
#define _GLIBCXX_MEMORY 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/unique_ptr.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
// The -*- C++ -*- dynamic memory management header.
|
||||
|
||||
// Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
//
|
||||
// GCC is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// GCC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file new
|
||||
* This is a Standard C++ Library header.
|
||||
*
|
||||
* The header @c new defines several functions to manage dynamic memory and
|
||||
* handling memory allocation errors; see
|
||||
* http://gcc.gnu.org/onlinedocs/libstdc++/18_support/howto.html#4 for more.
|
||||
*/
|
||||
|
||||
#ifndef _NEW
|
||||
#define _NEW
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/c++config.h"
|
||||
// #include <exception>
|
||||
|
||||
#include <new.h> // Arduino's version of the <new> header
|
||||
|
||||
#pragma GCC visibility push(default)
|
||||
|
||||
extern "C++" {
|
||||
|
||||
namespace std
|
||||
{
|
||||
#if 0
|
||||
/**
|
||||
* @brief Exception possibly thrown by @c new.
|
||||
* @ingroup exceptions
|
||||
*
|
||||
* @c bad_alloc (or classes derived from it) is used to report allocation
|
||||
* errors from the throwing forms of @c new. */
|
||||
class bad_alloc : public exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() throw() { }
|
||||
|
||||
// This declaration is not useless:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
|
||||
virtual ~bad_alloc() throw();
|
||||
|
||||
// See comment in eh_exception.cc.
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
class bad_array_new_length : public bad_alloc
|
||||
{
|
||||
public:
|
||||
bad_array_new_length() throw() { };
|
||||
|
||||
// This declaration is not useless:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
|
||||
virtual ~bad_array_new_length() throw();
|
||||
|
||||
// See comment in eh_exception.cc.
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // 0
|
||||
|
||||
#if __cpp_aligned_new
|
||||
enum class align_val_t: size_t {};
|
||||
#endif
|
||||
|
||||
#if !defined(NEW_H) || defined(__AVR_ATmega4809__) || defined(ARDUINO_TEENSY2PP) // already defined in Arduino's version of <new>
|
||||
struct nothrow_t
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
explicit nothrow_t() = default;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern const nothrow_t nothrow;
|
||||
|
||||
/** If you write your own error handler to be called by @c new, it must
|
||||
* be of this type. */
|
||||
typedef void (*new_handler)();
|
||||
|
||||
/// Takes a replacement handler as the argument, returns the
|
||||
/// previous handler.
|
||||
new_handler set_new_handler(new_handler) throw();
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
/// Return the current new handler.
|
||||
new_handler get_new_handler() noexcept;
|
||||
#endif
|
||||
#endif // NEW_H
|
||||
} // namespace std
|
||||
|
||||
//@{
|
||||
#if !defined(NEW_H) || defined(__AVR_ATmega4809__) || defined(ARDUINO_TEENSY2PP) // already defined in Arduino's version of <new>
|
||||
/** These are replaceable signatures:
|
||||
* - normal single new and delete (no arguments, throw @c bad_alloc on error)
|
||||
* - normal array new and delete (same)
|
||||
* - @c nothrow single new and delete (take a @c nothrow argument, return
|
||||
* @c NULL on error)
|
||||
* - @c nothrow array new and delete (same)
|
||||
*
|
||||
* Placement new and delete signatures (take a memory address argument,
|
||||
* does nothing) may not be replaced by a user's program.
|
||||
*/
|
||||
#ifndef __AVR_ATmega4809__
|
||||
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
|
||||
__attribute__((__externally_visible__));
|
||||
void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
|
||||
__attribute__((__externally_visible__));
|
||||
void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
#endif
|
||||
#if __cpp_sized_deallocation
|
||||
void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
#endif
|
||||
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
|
||||
__attribute__((__externally_visible__));
|
||||
#if __cpp_aligned_new
|
||||
void* operator new(std::size_t, std::align_val_t)
|
||||
__attribute__((__externally_visible__));
|
||||
void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void operator delete(void*, std::align_val_t)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void operator delete(void*, std::align_val_t, const std::nothrow_t&)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void* operator new[](std::size_t, std::align_val_t)
|
||||
__attribute__((__externally_visible__));
|
||||
void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void operator delete[](void*, std::align_val_t)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void operator delete[](void*, std::align_val_t, const std::nothrow_t&)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
#if __cpp_sized_deallocation
|
||||
void operator delete(void*, std::size_t, std::align_val_t)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
void operator delete[](void*, std::size_t, std::align_val_t)
|
||||
_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
|
||||
#endif // __cpp_sized_deallocation
|
||||
#endif // __cpp_aligned_new
|
||||
|
||||
// Default placement versions of operator new.
|
||||
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
|
||||
{ return __p; }
|
||||
inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
|
||||
{ return __p; }
|
||||
|
||||
// Default placement versions of operator delete.
|
||||
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
|
||||
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
|
||||
#endif // NEW_H
|
||||
//@}
|
||||
} // extern "C++"
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
#if __GNUC__ >= 7
|
||||
# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
|
||||
#elif defined __has_builtin
|
||||
// For non-GNU compilers:
|
||||
# if __has_builtin(__builtin_launder)
|
||||
# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
|
||||
namespace std
|
||||
{
|
||||
#define __cpp_lib_launder 201606
|
||||
/// Pointer optimization barrier [ptr.launder]
|
||||
template<typename _Tp>
|
||||
constexpr _Tp*
|
||||
launder(_Tp* __p) noexcept
|
||||
{ return __builtin_launder(__p); }
|
||||
|
||||
// The program is ill-formed if T is a function type or
|
||||
// (possibly cv-qualified) void.
|
||||
|
||||
template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
|
||||
void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete;
|
||||
template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
|
||||
void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete;
|
||||
|
||||
void launder(void*) = delete;
|
||||
void launder(const void*) = delete;
|
||||
void launder(volatile void*) = delete;
|
||||
void launder(const volatile void*) = delete;
|
||||
}
|
||||
#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
|
||||
#undef _GLIBCXX_HAVE_BUILTIN_LAUNDER
|
||||
#endif // C++17
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
// <numeric> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2017 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996,1997
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/** @file include/numeric
|
||||
* This is a Standard C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_NUMERIC
|
||||
#define _GLIBCXX_NUMERIC 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include "bits/c++config.h"
|
||||
#include "bits/stl_iterator_base_types.h"
|
||||
#include "bits/stl_numeric.h"
|
||||
|
||||
#ifdef _GLIBCXX_PARALLEL
|
||||
# include <parallel/numeric>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup numerics Numerics
|
||||
*
|
||||
* Components for performing numeric operations. Includes support for
|
||||
* for complex number types, random number generation, numeric
|
||||
* (n-at-a-time) arrays, generalized numeric algorithms, and special
|
||||
* math functions.
|
||||
*/
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
#include "type_traits"
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace __detail
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
// std::abs is not constexpr and doesn't support unsigned integers.
|
||||
template<typename _Tp>
|
||||
constexpr
|
||||
enable_if_t<__and_<is_integral<_Tp>, is_signed<_Tp>>::value, _Tp>
|
||||
__abs_integral(_Tp __val)
|
||||
{ return __val < 0 ? -__val : __val; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr
|
||||
enable_if_t<__and_<is_integral<_Tp>, is_unsigned<_Tp>>::value, _Tp>
|
||||
__abs_integral(_Tp __val)
|
||||
{ return __val; }
|
||||
|
||||
void __abs_integral(bool) = delete;
|
||||
|
||||
template<typename _Mn, typename _Nn>
|
||||
constexpr common_type_t<_Mn, _Nn>
|
||||
__gcd(_Mn __m, _Nn __n)
|
||||
{
|
||||
return __m == 0 ? __detail::__abs_integral(__n)
|
||||
: __n == 0 ? __detail::__abs_integral(__m)
|
||||
: __detail::__gcd(__n, __m % __n);
|
||||
}
|
||||
|
||||
/// Least common multiple
|
||||
template<typename _Mn, typename _Nn>
|
||||
constexpr common_type_t<_Mn, _Nn>
|
||||
__lcm(_Mn __m, _Nn __n)
|
||||
{
|
||||
return (__m != 0 && __n != 0)
|
||||
? (__detail::__abs_integral(__m) / __detail::__gcd(__m, __n))
|
||||
* __detail::__abs_integral(__n)
|
||||
: 0;
|
||||
}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
|
||||
#define __cpp_lib_gcd_lcm 201606
|
||||
// These were used in drafts of SD-6:
|
||||
#define __cpp_lib_gcd 201606
|
||||
#define __cpp_lib_lcm 201606
|
||||
|
||||
/// Greatest common divisor
|
||||
template<typename _Mn, typename _Nn>
|
||||
constexpr common_type_t<_Mn, _Nn>
|
||||
gcd(_Mn __m, _Nn __n)
|
||||
{
|
||||
static_assert(is_integral<_Mn>::value, "gcd arguments are integers");
|
||||
static_assert(is_integral<_Nn>::value, "gcd arguments are integers");
|
||||
static_assert(!is_same<_Mn, bool>::value, "gcd arguments are not bools");
|
||||
static_assert(!is_same<_Nn, bool>::value, "gcd arguments are not bools");
|
||||
return __detail::__gcd(__m, __n);
|
||||
}
|
||||
|
||||
/// Least common multiple
|
||||
template<typename _Mn, typename _Nn>
|
||||
constexpr common_type_t<_Mn, _Nn>
|
||||
lcm(_Mn __m, _Nn __n)
|
||||
{
|
||||
static_assert(is_integral<_Mn>::value, "lcm arguments are integers");
|
||||
static_assert(is_integral<_Nn>::value, "lcm arguments are integers");
|
||||
static_assert(!is_same<_Mn, bool>::value, "lcm arguments are not bools");
|
||||
static_assert(!is_same<_Nn, bool>::value, "lcm arguments are not bools");
|
||||
return __detail::__lcm(__m, __n);
|
||||
}
|
||||
|
||||
#endif // C++17
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
|
||||
#endif /* _GLIBCXX_NUMERIC */
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue