forked from OctaForge/libostd
more noexcept and readme note
This commit is contained in:
parent
1586cedd17
commit
519c9c7624
23
README.md
23
README.md
|
@ -53,3 +53,26 @@ or clang, etc.).
|
||||||
|
|
||||||
Windows is supported with GCC (MinGW) and Clang. The MS C runtime is supported
|
Windows is supported with GCC (MinGW) and Clang. The MS C runtime is supported
|
||||||
as well, so compiling with Clang targeting MSVC compatibility will work.
|
as well, so compiling with Clang targeting MSVC compatibility will work.
|
||||||
|
|
||||||
|
## Exceptions
|
||||||
|
|
||||||
|
The library is written with the idea that no API in it ever throws exceptions (with
|
||||||
|
possibly some rare... exceptions ;)). However, this does not mean it cannot be used
|
||||||
|
in code that utilizes exceptions. Because of this, the library attempts to provide
|
||||||
|
some degree of exception safety as well as proper `noexcept` annotations. It also
|
||||||
|
provides type traits to check things such as whether something can be constructed
|
||||||
|
or assigned to without throwing.
|
||||||
|
|
||||||
|
This is currently a work in progress though. Here is a list of files where things
|
||||||
|
have been correctly annotated:
|
||||||
|
|
||||||
|
* array.hh
|
||||||
|
* initializer_list.hh
|
||||||
|
* memory.hh
|
||||||
|
* new.hh
|
||||||
|
* platform.hh
|
||||||
|
* utility.hh
|
||||||
|
* type_traits.hh
|
||||||
|
|
||||||
|
This list will expand over time. As for exception safety of containers, it's is
|
||||||
|
currently not done/checked. They will be made exception safe over time too.
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "ostd/algorithm.hh"
|
#include "ostd/algorithm.hh"
|
||||||
#include "ostd/range.hh"
|
#include "ostd/range.hh"
|
||||||
#include "ostd/string.hh"
|
#include "ostd/string.hh"
|
||||||
|
#include "ostd/utility.hh"
|
||||||
#include "ostd/internal/tuple.hh"
|
#include "ostd/internal/tuple.hh"
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
|
@ -27,53 +28,53 @@ struct Array {
|
||||||
using Range = PointerRange<T>;
|
using Range = PointerRange<T>;
|
||||||
using ConstRange = PointerRange<T const>;
|
using ConstRange = PointerRange<T const>;
|
||||||
|
|
||||||
T &operator[](Size i) { return p_buf[i]; }
|
T &operator[](Size i) noexcept { return p_buf[i]; }
|
||||||
T const &operator[](Size i) const { return p_buf[i]; }
|
T const &operator[](Size i) const noexcept { return p_buf[i]; }
|
||||||
|
|
||||||
T *at(Size i) {
|
T *at(Size i) noexcept {
|
||||||
if (!in_range(i)) {
|
if (!in_range(i)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &p_buf[i];
|
return &p_buf[i];
|
||||||
}
|
}
|
||||||
T const *at(Size i) const {
|
T const *at(Size i) const noexcept {
|
||||||
if (!in_range(i)) {
|
if (!in_range(i)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &p_buf[i];
|
return &p_buf[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
T &front() { return p_buf[0]; }
|
T &front() noexcept { return p_buf[0]; }
|
||||||
T const &front() const { return p_buf[0]; }
|
T const &front() const noexcept { return p_buf[0]; }
|
||||||
|
|
||||||
T &back() { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
T &back() noexcept { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
||||||
T const &back() const { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
T const &back() const noexcept { return p_buf[(N > 0) ? (N - 1) : 0]; }
|
||||||
|
|
||||||
Size size() const { return N; }
|
Size size() const noexcept { return N; }
|
||||||
Size max_size() const { return Size(~0) / sizeof(T); }
|
Size max_size() const noexcept { return Size(~0) / sizeof(T); }
|
||||||
|
|
||||||
bool empty() const { return N == 0; }
|
bool empty() const noexcept { return N == 0; }
|
||||||
|
|
||||||
bool in_range(Size idx) { return idx < N; }
|
bool in_range(Size idx) noexcept { return idx < N; }
|
||||||
bool in_range(int idx) { return idx >= 0 && Size(idx) < N; }
|
bool in_range(int idx) noexcept { return idx >= 0 && Size(idx) < N; }
|
||||||
bool in_range(ConstPointer ptr) {
|
bool in_range(ConstPointer ptr) noexcept {
|
||||||
return ptr >= &p_buf[0] && ptr < &p_buf[N];
|
return ptr >= &p_buf[0] && ptr < &p_buf[N];
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer data() { return p_buf; }
|
Pointer data() noexcept { return p_buf; }
|
||||||
ConstPointer data() const { return p_buf; }
|
ConstPointer data() const noexcept { return p_buf; }
|
||||||
|
|
||||||
Range iter() {
|
Range iter() noexcept {
|
||||||
return Range(p_buf, p_buf + N);
|
return Range(p_buf, p_buf + N);
|
||||||
}
|
}
|
||||||
ConstRange iter() const {
|
ConstRange iter() const noexcept {
|
||||||
return ConstRange(p_buf, p_buf + N);
|
return ConstRange(p_buf, p_buf + N);
|
||||||
}
|
}
|
||||||
ConstRange citer() const {
|
ConstRange citer() const noexcept {
|
||||||
return ConstRange(p_buf, p_buf + N);
|
return ConstRange(p_buf, p_buf + N);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Array &v) {
|
void swap(Array &v) noexcept(noexcept(swap(declval<T &>(), declval<T &>()))) {
|
||||||
ostd::swap_ranges(iter(), v.iter());
|
ostd::swap_ranges(iter(), v.iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,22 +90,22 @@ struct TupleElementBase<I, Array<T, N>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<Size I, typename T, Size N>
|
template<Size I, typename T, Size N>
|
||||||
inline TupleElement<I, Array<T, N>> &get(Array<T, N> &a) {
|
inline TupleElement<I, Array<T, N>> &get(Array<T, N> &a) noexcept {
|
||||||
return a[I];
|
return a[I];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, Size N>
|
template<Size I, typename T, Size N>
|
||||||
inline TupleElement<I, Array<T, N>> const &get(Array<T, N> const &a) {
|
inline TupleElement<I, Array<T, N>> const &get(Array<T, N> const &a) noexcept {
|
||||||
return a[I];
|
return a[I];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, Size N>
|
template<Size I, typename T, Size N>
|
||||||
inline TupleElement<I, Array<T, N>> &&get(Array<T, N> &&a) {
|
inline TupleElement<I, Array<T, N>> &&get(Array<T, N> &&a) noexcept {
|
||||||
return move(a.p_buf[I]);
|
return move(a.p_buf[I]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, Size N>
|
template<Size I, typename T, Size N>
|
||||||
inline TupleElement<I, Array<T, N>> const &&get(Array<T, N> const &&a) {
|
inline TupleElement<I, Array<T, N>> const &&get(Array<T, N> const &&a) noexcept {
|
||||||
return move(a.p_buf[I]);
|
return move(a.p_buf[I]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,16 @@ class initializer_list {
|
||||||
T const *p_buf;
|
T const *p_buf;
|
||||||
ostd::Size p_len;
|
ostd::Size p_len;
|
||||||
|
|
||||||
constexpr initializer_list(T const *v, ostd::Size n): p_buf(v), p_len(n) {}
|
constexpr initializer_list(T const *v, ostd::Size n) noexcept:
|
||||||
|
p_buf(v), p_len(n)
|
||||||
|
{}
|
||||||
public:
|
public:
|
||||||
constexpr initializer_list(): p_buf(nullptr), p_len(0) {}
|
constexpr initializer_list() noexcept: p_buf(nullptr), p_len(0) {}
|
||||||
|
|
||||||
constexpr ostd::Size size() const { return p_len; }
|
constexpr ostd::Size size() const noexcept { return p_len; }
|
||||||
|
|
||||||
constexpr T const *begin() const { return p_buf; }
|
constexpr T const *begin() const noexcept { return p_buf; }
|
||||||
constexpr T const *end() const { return p_buf + p_len; }
|
constexpr T const *end() const noexcept { return p_buf + p_len; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,12 +42,12 @@ template<typename T>
|
||||||
using InitializerList = std::initializer_list<T>;
|
using InitializerList = std::initializer_list<T>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PointerRange<T const> iter(std::initializer_list<T> init) {
|
PointerRange<T const> iter(std::initializer_list<T> init) noexcept {
|
||||||
return PointerRange<T const>(init.begin(), init.end());
|
return PointerRange<T const>(init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PointerRange<T const> citer(std::initializer_list<T> init) {
|
PointerRange<T const> citer(std::initializer_list<T> init) noexcept {
|
||||||
return PointerRange<T const>(init.begin(), init.end());
|
return PointerRange<T const>(init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,16 +69,16 @@ template<typename ...A>
|
||||||
constexpr bool IsTupleLike<Tuple<A...>> = true;
|
constexpr bool IsTupleLike<Tuple<A...>> = true;
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &);
|
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline const TupleElement<I, Tuple<A...>> &get(const Tuple<A...> &);
|
inline const TupleElement<I, Tuple<A...>> &get(const Tuple<A...> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&);
|
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline const TupleElement<I, Tuple<A...>> &&get(const Tuple<A...> &&);
|
inline const TupleElement<I, Tuple<A...>> &&get(const Tuple<A...> &&) noexcept;
|
||||||
|
|
||||||
/* pair specializations */
|
/* pair specializations */
|
||||||
|
|
||||||
|
@ -86,16 +86,16 @@ template<typename T, typename U>
|
||||||
constexpr bool IsTupleLike<Pair<T, U>> = true;
|
constexpr bool IsTupleLike<Pair<T, U>> = true;
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> &get(Pair<T, U> &);
|
inline TupleElement<I, Pair<T, U>> &get(Pair<T, U> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline const TupleElement<I, Pair<T, U>> &get(const Pair<T, U> &);
|
inline const TupleElement<I, Pair<T, U>> &get(const Pair<T, U> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> &&get(Pair<T, U> &&);
|
inline TupleElement<I, Pair<T, U>> &&get(Pair<T, U> &&) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline const TupleElement<I, Pair<T, U>> &&get(const Pair<T, U> &&);
|
inline const TupleElement<I, Pair<T, U>> &&get(const Pair<T, U> &&) noexcept;
|
||||||
|
|
||||||
/* array specializations */
|
/* array specializations */
|
||||||
|
|
||||||
|
@ -103,16 +103,16 @@ template<typename T, Size I>
|
||||||
constexpr bool IsTupleLike<Array<T, I>> = true;
|
constexpr bool IsTupleLike<Array<T, I>> = true;
|
||||||
|
|
||||||
template<Size I, typename T, Size S>
|
template<Size I, typename T, Size S>
|
||||||
inline T &get(Array<T, S> &);
|
inline T &get(Array<T, S> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, Size S>
|
template<Size I, typename T, Size S>
|
||||||
inline const T &get(const Array<T, S> &);
|
inline const T &get(const Array<T, S> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, Size S>
|
template<Size I, typename T, Size S>
|
||||||
inline T &&get(Array<T, S> &&);
|
inline T &&get(Array<T, S> &&) noexcept;
|
||||||
|
|
||||||
template<Size I, typename T, Size S>
|
template<Size I, typename T, Size S>
|
||||||
inline const T &&get(const Array<T, S> &&);
|
inline const T &&get(const Array<T, S> &&) noexcept;
|
||||||
|
|
||||||
/* make tuple indices */
|
/* make tuple indices */
|
||||||
|
|
||||||
|
|
|
@ -102,40 +102,40 @@ namespace ostd {
|
||||||
#if defined(OSTD_TOOLCHAIN_GNU)
|
#if defined(OSTD_TOOLCHAIN_GNU)
|
||||||
|
|
||||||
/* using gcc/clang builtins */
|
/* using gcc/clang builtins */
|
||||||
inline uint16_t endian_swap16(uint16_t x) {
|
inline uint16_t endian_swap16(uint16_t x) noexcept {
|
||||||
return __builtin_bswap16(x);
|
return __builtin_bswap16(x);
|
||||||
}
|
}
|
||||||
inline uint32_t endian_swap32(uint32_t x) {
|
inline uint32_t endian_swap32(uint32_t x) noexcept {
|
||||||
return __builtin_bswap32(x);
|
return __builtin_bswap32(x);
|
||||||
}
|
}
|
||||||
inline uint64_t endian_swap64(uint64_t x) {
|
inline uint64_t endian_swap64(uint64_t x) noexcept {
|
||||||
return __builtin_bswap64(x);
|
return __builtin_bswap64(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(OSTD_TOOLCHAIN_MSVC)
|
#elif defined(OSTD_TOOLCHAIN_MSVC)
|
||||||
|
|
||||||
/* using msvc builtins */
|
/* using msvc builtins */
|
||||||
inline uint16_t endian_swap16(uint16_t x) {
|
inline uint16_t endian_swap16(uint16_t x) noexcept {
|
||||||
return _byteswap_ushort(x);
|
return _byteswap_ushort(x);
|
||||||
}
|
}
|
||||||
inline uint32_t endian_swap32(uint32_t x) {
|
inline uint32_t endian_swap32(uint32_t x) noexcept {
|
||||||
/* win64 is llp64 */
|
/* win64 is llp64 */
|
||||||
return _byteswap_ulong(x);
|
return _byteswap_ulong(x);
|
||||||
}
|
}
|
||||||
inline uint64_t endian_swap64(uint64_t x) {
|
inline uint64_t endian_swap64(uint64_t x) noexcept {
|
||||||
return _byteswap_uint64(x);
|
return _byteswap_uint64(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* fallback */
|
/* fallback */
|
||||||
inline uint16_t endian_swap16(uint16_t x) {
|
inline uint16_t endian_swap16(uint16_t x) noexcept {
|
||||||
return (x << 8) | (x >> 8);
|
return (x << 8) | (x >> 8);
|
||||||
}
|
}
|
||||||
inline uint32_t endian_swap32(uint32_t x) {
|
inline uint32_t endian_swap32(uint32_t x) noexcept {
|
||||||
return (x << 24) | (x >> 24) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000);
|
return (x << 24) | (x >> 24) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000);
|
||||||
}
|
}
|
||||||
inline uint64_t endian_swap64(uint64_t x) {
|
inline uint64_t endian_swap64(uint64_t x) noexcept {
|
||||||
return endian_swap32(
|
return endian_swap32(
|
||||||
uint32_t(x >> 32)) | (uint64_t(endian_swap32(uint32_t(x))) << 32
|
uint32_t(x >> 32)) | (uint64_t(endian_swap32(uint32_t(x))) << 32
|
||||||
);
|
);
|
||||||
|
|
|
@ -323,16 +323,16 @@ class Tuple {
|
||||||
Base p_base;
|
Base p_base;
|
||||||
|
|
||||||
template<Size I, typename ...T>
|
template<Size I, typename ...T>
|
||||||
friend TupleElement<I, Tuple<T...>> &get(Tuple<T...> &);
|
friend TupleElement<I, Tuple<T...>> &get(Tuple<T...> &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...T>
|
template<Size I, typename ...T>
|
||||||
friend TupleElement<I, Tuple<T...>> const &get(Tuple<T...> const &);
|
friend TupleElement<I, Tuple<T...>> const &get(Tuple<T...> const &) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...T>
|
template<Size I, typename ...T>
|
||||||
friend TupleElement<I, Tuple<T...>> &&get(Tuple<T...> &&);
|
friend TupleElement<I, Tuple<T...>> &&get(Tuple<T...> &&) noexcept;
|
||||||
|
|
||||||
template<Size I, typename ...T>
|
template<Size I, typename ...T>
|
||||||
friend TupleElement<I, Tuple<T...>> const &&get(Tuple<T...> const &&);
|
friend TupleElement<I, Tuple<T...>> const &&get(Tuple<T...> const &&) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool D = true, typename = EnableIf<
|
template<bool D = true, typename = EnableIf<
|
||||||
|
@ -484,26 +484,26 @@ public:
|
||||||
/* get */
|
/* get */
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &t) {
|
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &t) noexcept {
|
||||||
using Type = TupleElement<I, Tuple<A...>>;
|
using Type = TupleElement<I, Tuple<A...>>;
|
||||||
return static_cast<detail::TupleLeaf<I, Type> &>(t.p_base).get();
|
return static_cast<detail::TupleLeaf<I, Type> &>(t.p_base).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> const &get(Tuple<A...> const &t) {
|
inline TupleElement<I, Tuple<A...>> const &get(Tuple<A...> const &t) noexcept {
|
||||||
using Type = TupleElement<I, Tuple<A...>>;
|
using Type = TupleElement<I, Tuple<A...>>;
|
||||||
return static_cast<detail::TupleLeaf<I, Type> const &>(t.p_base).get();
|
return static_cast<detail::TupleLeaf<I, Type> const &>(t.p_base).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&t) {
|
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&t) noexcept {
|
||||||
using Type = TupleElement<I, Tuple<A...>>;
|
using Type = TupleElement<I, Tuple<A...>>;
|
||||||
return static_cast<Type &&>(
|
return static_cast<Type &&>(
|
||||||
static_cast<detail::TupleLeaf<I, Type> &&>(t.p_base).get());
|
static_cast<detail::TupleLeaf<I, Type> &&>(t.p_base).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename ...A>
|
template<Size I, typename ...A>
|
||||||
inline TupleElement<I, Tuple<A...>> const &&get(Tuple<A...> const &&t) {
|
inline TupleElement<I, Tuple<A...>> const &&get(Tuple<A...> const &&t) noexcept {
|
||||||
using Type = TupleElement<I, Tuple<A...>>;
|
using Type = TupleElement<I, Tuple<A...>>;
|
||||||
return static_cast<Type const &&>(
|
return static_cast<Type const &&>(
|
||||||
static_cast<detail::TupleLeaf<I, Type> const &&>(t.p_base).get());
|
static_cast<detail::TupleLeaf<I, Type> const &&>(t.p_base).get());
|
||||||
|
|
|
@ -16,19 +16,19 @@ namespace ostd {
|
||||||
/* move */
|
/* move */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr RemoveReference<T> &&move(T &&v) {
|
inline constexpr RemoveReference<T> &&move(T &&v) noexcept {
|
||||||
return static_cast<RemoveReference<T> &&>(v);
|
return static_cast<RemoveReference<T> &&>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward */
|
/* forward */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr T &&forward(RemoveReference<T> &v) {
|
inline constexpr T &&forward(RemoveReference<T> &v) noexcept {
|
||||||
return static_cast<T &&>(v);
|
return static_cast<T &&>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr T &&forward(RemoveReference<T> &&v) {
|
inline constexpr T &&forward(RemoveReference<T> &&v) noexcept {
|
||||||
return static_cast<T &&>(v);
|
return static_cast<T &&>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,14 +58,14 @@ namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void swap_fb(
|
inline void swap_fb(
|
||||||
T &a, T &b, EnableIf<decltype(test_swap<T>(0))::value, bool> = true
|
T &a, T &b, EnableIf<decltype(test_swap<T>(0))::value, bool> = true
|
||||||
) {
|
) noexcept(noexcept(a.swap(b))) {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void swap_fb(
|
inline void swap_fb(
|
||||||
T &a, T &b, EnableIf<!decltype(test_swap<T>(0))::value, bool> = true
|
T &a, T &b, EnableIf<!decltype(test_swap<T>(0))::value, bool> = true
|
||||||
) {
|
) noexcept(IsNothrowMoveConstructible<T> && IsNothrowMoveAssignable<T>) {
|
||||||
T c(move(a));
|
T c(move(a));
|
||||||
a = move(b);
|
a = move(b);
|
||||||
b = move(c);
|
b = move(c);
|
||||||
|
@ -73,24 +73,30 @@ namespace detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void swap(T &a, T &b) {
|
inline void swap(T &a, T &b) noexcept(noexcept(detail::swap_fb(a, b))) {
|
||||||
detail::swap_fb(a, b);
|
detail::swap_fb(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, Size N>
|
template<typename T, Size N>
|
||||||
inline void swap(T (&a)[N], T (&b)[N]) {
|
inline void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))) {
|
||||||
for (Size i = 0; i < N; ++i) {
|
for (Size i = 0; i < N; ++i) {
|
||||||
swap(a[i], b[i]);
|
swap(a[i], b[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T>
|
namespace adl_swap {
|
||||||
inline void swap_adl(T &a, T &b) {
|
|
||||||
using ostd::swap;
|
using ostd::swap;
|
||||||
|
template<typename T>
|
||||||
|
inline void swap_adl(T &a, T &b) noexcept(noexcept(swap(a, b))) {
|
||||||
swap(a, b);
|
swap(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
inline void swap_adl(T &a, T &b) noexcept(noexcept(adl_swap::swap_adl(a, b))) {
|
||||||
|
adl_swap::swap_adl(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* pair */
|
/* pair */
|
||||||
|
|
||||||
|
@ -145,7 +151,9 @@ struct Pair {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair &operator=(Pair &&v) {
|
Pair &operator=(Pair &&v) noexcept(
|
||||||
|
IsNothrowMoveAssignable<T> && IsNothrowMoveAssignable<U>
|
||||||
|
) {
|
||||||
first = move(v.first);
|
first = move(v.first);
|
||||||
second = move(v.second);
|
second = move(v.second);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -158,7 +166,10 @@ struct Pair {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Pair &v) {
|
void swap(Pair &v) noexcept(
|
||||||
|
noexcept(detail::swap_adl(first, v.first)) &&
|
||||||
|
noexcept(detail::swap_adl(second, v.second))
|
||||||
|
) {
|
||||||
detail::swap_adl(first, v.first);
|
detail::swap_adl(first, v.first);
|
||||||
detail::swap_adl(second, v.second);
|
detail::swap_adl(second, v.second);
|
||||||
}
|
}
|
||||||
|
@ -284,22 +295,22 @@ namespace detail {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> &get(Pair<T, U> &p) {
|
inline TupleElement<I, Pair<T, U>> &get(Pair<T, U> &p) noexcept {
|
||||||
return detail::GetPair<I>::get(p);
|
return detail::GetPair<I>::get(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> const &get(Pair<T, U> const &p) {
|
inline TupleElement<I, Pair<T, U>> const &get(Pair<T, U> const &p) noexcept {
|
||||||
return detail::GetPair<I>::get(p);
|
return detail::GetPair<I>::get(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> &&get(Pair<T, U> &&p) {
|
inline TupleElement<I, Pair<T, U>> &&get(Pair<T, U> &&p) noexcept {
|
||||||
return detail::GetPair<I>::get(move(p));
|
return detail::GetPair<I>::get(move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Size I, typename T, typename U>
|
template<Size I, typename T, typename U>
|
||||||
inline TupleElement<I, Pair<T, U>> const &&get(Pair<T, U> const &&p) {
|
inline TupleElement<I, Pair<T, U>> const &&get(Pair<T, U> const &&p) noexcept {
|
||||||
return detail::GetPair<I>::get(move(p));
|
return detail::GetPair<I>::get(move(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue