2015-07-11 01:38:11 +00:00
|
|
|
/* Tuples or OctaSTD. Partially taken from the libc++ project.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_TUPLE_HH
|
|
|
|
#define OSTD_TUPLE_HH
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/internal/tuple.hh"
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/types.hh"
|
|
|
|
#include "ostd/type_traits.hh"
|
|
|
|
#include "ostd/memory.hh"
|
|
|
|
#include "ostd/utility.hh"
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
/* tuple size */
|
|
|
|
|
|
|
|
template<typename ...T> struct TupleSize<Tuple<T...>>:
|
2016-01-16 18:31:44 +00:00
|
|
|
Constant<Size, sizeof...(T)> {};
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
/* tuple element */
|
|
|
|
|
2015-07-11 14:17:12 +00:00
|
|
|
template<Size I, typename ...T>
|
|
|
|
struct TupleElementBase<I, Tuple<T...>> {
|
|
|
|
using Type = typename TupleElementBase<I, detail::TupleTypes<T...>>::Type;
|
|
|
|
};
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
/* tuple leaf */
|
|
|
|
|
|
|
|
namespace detail {
|
2016-01-12 21:45:26 +00:00
|
|
|
template<Size I, typename H, bool = IsEmpty<H>>
|
2015-07-11 01:38:11 +00:00
|
|
|
struct TupleLeaf {
|
|
|
|
constexpr TupleLeaf(): p_value() {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsReference<H>,
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to default construct a reference element in a tuple");
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 0>, const A &): p_value() {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsReference<H>,
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to default construct a reference element in a tuple");
|
|
|
|
}
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 1>, const A &a): p_value(allocator_arg, a) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsReference<H>,
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to default construct a reference element in a tuple");
|
|
|
|
}
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 2>, const A &a): p_value(a) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsReference<H>,
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to default construct a reference element in a tuple");
|
|
|
|
}
|
|
|
|
|
2016-01-14 19:32:22 +00:00
|
|
|
template<typename T, typename = EnableIf<
|
|
|
|
!IsSame<Decay<T>, TupleLeaf> && IsConstructible<H, T>
|
|
|
|
>>
|
2015-07-11 01:38:11 +00:00
|
|
|
explicit TupleLeaf(T &&t): p_value(forward<T>(t)) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsReference<H> ||
|
|
|
|
(IsLvalueReference<H> &&
|
|
|
|
(IsLvalueReference<T> ||
|
2015-07-11 01:38:11 +00:00
|
|
|
IsSame<RemoveReference<T>,
|
2016-01-12 22:24:40 +00:00
|
|
|
ReferenceWrapper<RemoveReference<H>>>)) ||
|
2016-01-12 21:45:26 +00:00
|
|
|
(IsRvalueReference<H> &&
|
|
|
|
!IsLvalueReference<T>),
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to construct a reference element in a tuple with an rvalue");
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 0>, const A &, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
p_value(forward<T>(t)) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsLvalueReference<H> ||
|
|
|
|
(IsLvalueReference<H> &&
|
|
|
|
(IsLvalueReference<T> ||
|
2015-07-11 01:38:11 +00:00
|
|
|
IsSame<RemoveReference<T>,
|
2016-01-12 22:24:40 +00:00
|
|
|
ReferenceWrapper<RemoveReference<H>>>)),
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to construct a reference element in a tuple with an rvalue");
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 1>, const A &a, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
p_value(allocator_arg, a, forward<T>(t)) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsLvalueReference<H> ||
|
|
|
|
(IsLvalueReference<H> &&
|
|
|
|
(IsLvalueReference<T> ||
|
2015-07-11 01:38:11 +00:00
|
|
|
IsSame<RemoveReference<T>,
|
2016-01-12 22:24:40 +00:00
|
|
|
ReferenceWrapper<RemoveReference<H>>>)),
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to construct a reference element in a tuple with an rvalue");
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 2>, const A &a, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
p_value(forward<T>(t), a) {
|
2016-01-12 21:45:26 +00:00
|
|
|
static_assert(!IsLvalueReference<H> ||
|
|
|
|
(IsLvalueReference<H> &&
|
|
|
|
(IsLvalueReference<T> ||
|
2015-07-11 01:38:11 +00:00
|
|
|
IsSame<RemoveReference<T>,
|
2016-01-12 22:24:40 +00:00
|
|
|
ReferenceWrapper<RemoveReference<H>>>)),
|
2015-07-11 01:38:11 +00:00
|
|
|
"attempt to construct a reference element in a tuple with an rvalue");
|
|
|
|
}
|
|
|
|
|
|
|
|
TupleLeaf(const TupleLeaf &) = default;
|
|
|
|
TupleLeaf(TupleLeaf &&) = default;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
TupleLeaf &operator=(T &&t) {
|
|
|
|
p_value = forward<T>(t);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(TupleLeaf &t) {
|
2015-07-11 17:50:13 +00:00
|
|
|
swap_adl(get(), t.get());
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
H &get() { return p_value; }
|
|
|
|
const H &get() const { return p_value; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
TupleLeaf &operator=(const TupleLeaf &);
|
|
|
|
H p_value;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<Size I, typename H>
|
|
|
|
struct TupleLeaf<I, H, true>: private H {
|
|
|
|
constexpr TupleLeaf() {}
|
|
|
|
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 0>, const A &) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 1>, const A &a):
|
2015-07-11 01:38:11 +00:00
|
|
|
H(allocator_arg, a) {}
|
|
|
|
|
|
|
|
template<typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
TupleLeaf(Constant<int, 2>, const A &a): H(a) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2016-01-14 19:32:22 +00:00
|
|
|
template<typename T, typename = EnableIf<
|
|
|
|
!IsSame<Decay<T>, TupleLeaf> && IsConstructible<H, T>
|
|
|
|
>> explicit TupleLeaf(T &&t): H(forward<T>(t)) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 0>, const A &, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
H(forward<T>(t)) {}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 1>, const A &a, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
H(allocator_arg, a, forward<T>(t)) {}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-16 18:31:44 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 2>, const A &a, T &&t):
|
2015-07-11 01:38:11 +00:00
|
|
|
H(forward<T>(t), a) {}
|
|
|
|
|
|
|
|
TupleLeaf(const TupleLeaf &) = default;
|
|
|
|
TupleLeaf(TupleLeaf &&) = default;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
TupleLeaf &operator=(T &&t) {
|
|
|
|
H::operator=(forward<T>(t));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(TupleLeaf &t) {
|
2015-07-11 17:50:13 +00:00
|
|
|
swap_adl(get(), t.get());
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
H &get() { return (H &)*this; }
|
|
|
|
const H &get() const { return (const H &)*this; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
TupleLeaf &operator=(const TupleLeaf &);
|
|
|
|
};
|
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
/* internal utils */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename ...A>
|
|
|
|
inline void tuple_swallow(A &&...) {}
|
|
|
|
|
2016-01-12 22:24:40 +00:00
|
|
|
template<bool ...A> struct TupleAll:
|
2016-01-16 18:31:44 +00:00
|
|
|
Constant<bool, IsSame<TupleAll<A...>, TupleAll<(A, true)...>>> {};
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct TupleAllDefaultConstructible;
|
|
|
|
|
|
|
|
template<typename ...A>
|
|
|
|
struct TupleAllDefaultConstructible<TupleTypes<A...>>:
|
2016-01-12 22:09:40 +00:00
|
|
|
TupleAll<IsDefaultConstructible<A>...> {};
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* tuple implementation */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename, typename ...> struct TupleBase;
|
|
|
|
|
|
|
|
template<Size ...I, typename ...A>
|
|
|
|
struct TupleBase<TupleIndices<I...>, A...>: TupleLeaf<I, A>... {
|
|
|
|
constexpr TupleBase() {}
|
|
|
|
|
|
|
|
template<Size ...Ia, typename ...Aa,
|
|
|
|
Size ...Ib, typename ...Ab, typename ...T>
|
|
|
|
explicit TupleBase(TupleIndices<Ia...>, TupleTypes<Aa...>,
|
|
|
|
TupleIndices<Ib...>, TupleTypes<Ab...>,
|
|
|
|
T &&...t):
|
|
|
|
TupleLeaf<Ia, Aa>(forward<T>(t))...,
|
|
|
|
TupleLeaf<Ib, Ab>()... {}
|
|
|
|
|
|
|
|
template<typename Alloc, Size ...Ia, typename ...Aa,
|
|
|
|
Size ...Ib, typename ...Ab, typename ...T>
|
|
|
|
explicit TupleBase(AllocatorArg, const Alloc &a,
|
|
|
|
TupleIndices<Ia...>, TupleTypes<Aa...>,
|
|
|
|
TupleIndices<Ib...>, TupleTypes<Ab...>,
|
|
|
|
T &&...t):
|
|
|
|
TupleLeaf<Ia, Aa>(UsesAllocatorConstructor<Aa, Alloc, T>(), a,
|
|
|
|
forward<T>(t))...,
|
|
|
|
TupleLeaf<Ib, Ab>(UsesAllocatorConstructor<Ab, Alloc>(), a)...
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T, typename = EnableIf<
|
|
|
|
TupleConstructible<T, Tuple<A...>>::value
|
|
|
|
>> TupleBase(T &&t): TupleLeaf<I, A>(forward<
|
|
|
|
TupleElement<I, MakeTupleTypes<T>>
|
|
|
|
>(get<I>(t)))... {}
|
|
|
|
|
|
|
|
template<typename Alloc, typename T, typename = EnableIf<
|
|
|
|
TupleConvertible<T, Tuple<A...>>::value
|
|
|
|
>> TupleBase(AllocatorArg, const Alloc &a, T &&t):
|
|
|
|
TupleLeaf<I, A>(UsesAllocatorConstructor<
|
|
|
|
A, Alloc, TupleElement<I, MakeTupleTypes<T>>
|
|
|
|
>(), a, forward<TupleElement<I, MakeTupleTypes<T>>>(get<I>(t)))...
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
EnableIf<TupleAssignable<T, Tuple<A...>>::value, TupleBase &>
|
|
|
|
operator=(T &&t) {
|
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(forward<
|
|
|
|
TupleElement<I, MakeTupleTypes<T>>
|
|
|
|
>(get<I>(t)))...);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TupleBase(const TupleBase &) = default;
|
|
|
|
TupleBase(TupleBase &&) = default;
|
|
|
|
|
|
|
|
TupleBase &operator=(const TupleBase &t) {
|
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(((const TupleLeaf<I,
|
|
|
|
A> &)t).get())...);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TupleBase &operator=(TupleBase &&t) {
|
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(forward<A>
|
|
|
|
(((const TupleLeaf<I, A> &)t).get()))...);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(TupleBase &t) {
|
|
|
|
tuple_swallow(TupleLeaf<I, A>::swap((TupleLeaf<I, A> &)t)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename ...A>
|
|
|
|
class Tuple {
|
|
|
|
using Base = detail::TupleBase<detail::MakeTupleIndices<sizeof...(A)>, A...>;
|
|
|
|
Base p_base;
|
|
|
|
|
|
|
|
template<Size I, typename ...T>
|
|
|
|
friend TupleElement<I, Tuple<T...>> &get(Tuple<T...> &);
|
|
|
|
|
|
|
|
template<Size I, typename ...T>
|
2015-07-11 16:26:41 +00:00
|
|
|
friend const TupleElement<I, Tuple<T...>> &get(const Tuple<T...> &);
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<Size I, typename ...T>
|
2015-07-11 16:26:41 +00:00
|
|
|
friend TupleElement<I, Tuple<T...>> &&get(Tuple<T...> &&);
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
template<bool D = true, typename = EnableIf<
|
2016-01-12 22:09:40 +00:00
|
|
|
detail::TupleAll<(D && IsDefaultConstructible<A>)...>::value
|
2015-07-11 01:38:11 +00:00
|
|
|
>> Tuple() {}
|
|
|
|
|
|
|
|
explicit Tuple(const A &...t):
|
|
|
|
p_base(detail::MakeTupleIndices<sizeof...(A)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A)>(),
|
|
|
|
detail::MakeTupleIndices<0>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, 0>(), t...) {}
|
|
|
|
|
|
|
|
template<typename Alloc>
|
|
|
|
Tuple(AllocatorArg, const Alloc &a, const A &...t):
|
|
|
|
p_base(allocator_arg, a,
|
|
|
|
detail::MakeTupleIndices<sizeof...(A)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A)>(),
|
|
|
|
detail::MakeTupleIndices<0>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, 0>(), t...) {}
|
|
|
|
|
|
|
|
template<typename ...T, EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
|
|
|
detail::MakeTupleTypes<Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value &&
|
|
|
|
detail::TupleAllDefaultConstructible<
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value, bool
|
|
|
|
> = true>
|
|
|
|
Tuple(T &&...t):
|
|
|
|
p_base(detail::MakeTupleIndices<sizeof...(T)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(T)>(),
|
|
|
|
detail::MakeTupleIndices<sizeof...(A), sizeof...(T)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A), sizeof...(T)>(),
|
|
|
|
forward<T>(t)...) {}
|
|
|
|
|
|
|
|
template<typename ...T, EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConstructible<
|
|
|
|
Tuple<T...>,
|
|
|
|
detail::MakeTupleTypes<Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value &&
|
|
|
|
!detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
|
|
|
detail::MakeTupleTypes<Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value &&
|
|
|
|
detail::TupleAllDefaultConstructible<
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value, bool
|
|
|
|
> = true>
|
|
|
|
Tuple(T &&...t):
|
|
|
|
p_base(detail::MakeTupleIndices<sizeof...(T)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(T)>(),
|
|
|
|
detail::MakeTupleIndices<sizeof...(A), sizeof...(T)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A), sizeof...(T)>(),
|
|
|
|
forward<T>(t)...) {}
|
|
|
|
|
|
|
|
template<typename Alloc, typename ...T, typename = EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
|
|
|
detail::MakeTupleTypes<Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value &&
|
|
|
|
detail::TupleAllDefaultConstructible<
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T)
|
|
|
|
: sizeof...(A)
|
|
|
|
>
|
|
|
|
>::value
|
|
|
|
>> Tuple(AllocatorArg, const Alloc &a, T &&...t):
|
2015-07-11 14:06:42 +00:00
|
|
|
p_base(allocator_arg, a, detail::MakeTupleIndices<sizeof...(T)>(),
|
2015-07-11 01:38:11 +00:00
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(T)>(),
|
|
|
|
detail::MakeTupleIndices<sizeof...(A), sizeof...(T)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A), sizeof...(T)>(),
|
|
|
|
forward<T>(t)...) {}
|
|
|
|
|
|
|
|
template<typename T, EnableIf<
|
|
|
|
detail::TupleConvertible<T, Tuple>::value, bool
|
|
|
|
> = true> Tuple(T &&t): p_base(forward<T>(t)) {}
|
|
|
|
|
|
|
|
template<typename T, EnableIf<
|
|
|
|
detail::TupleConstructible<T, Tuple>::value &&
|
|
|
|
!detail::TupleConvertible<T, Tuple>::value, bool
|
|
|
|
> = true> Tuple(T &&t): p_base(forward<T>(t)) {}
|
|
|
|
|
|
|
|
template<typename Alloc, typename T, typename = EnableIf<
|
|
|
|
detail::TupleConvertible<T, Tuple>::value
|
|
|
|
>> Tuple(AllocatorArg, const Alloc &a, T &&t):
|
|
|
|
p_base(allocator_arg, a, forward<T>(t)) {}
|
|
|
|
|
|
|
|
template<typename T, typename = EnableIf<
|
|
|
|
detail::TupleAssignable<T, Tuple>::value
|
|
|
|
>> Tuple &operator=(T &&t) {
|
|
|
|
p_base.operator=(forward<T>(t));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(Tuple &t) {
|
|
|
|
p_base.swap(t.p_base);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> class Tuple<> {
|
|
|
|
public:
|
|
|
|
constexpr Tuple() {}
|
|
|
|
template<typename A> Tuple(AllocatorArg, const A &) {}
|
|
|
|
template<typename A> Tuple(AllocatorArg, const A &, const Tuple &) {}
|
|
|
|
void swap(Tuple &) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* get */
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
|
|
|
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &t) {
|
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
|
|
|
return ((detail::TupleLeaf<I, Type> &)t.p_base).get();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
|
|
|
inline const TupleElement<I, Tuple<A...>> &get(const Tuple<A...> &t) {
|
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
|
|
|
return ((const detail::TupleLeaf<I, Type> &)t.p_base).get();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
|
|
|
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&t) {
|
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
|
|
|
return ((detail::TupleLeaf<I, Type> &&)t.p_base).get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tie */
|
|
|
|
|
|
|
|
template<typename ...T>
|
|
|
|
inline Tuple<T &...> tie(T &...t) {
|
|
|
|
return Tuple<T &...>(t...);
|
|
|
|
}
|
|
|
|
|
2015-07-11 02:26:57 +00:00
|
|
|
/* ignore */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
struct Ignore {
|
|
|
|
template<typename T>
|
|
|
|
const Ignore &operator=(T &&) const { return *this; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static const detail::Ignore ignore = detail::Ignore();
|
|
|
|
|
|
|
|
/* make tuple */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename T>
|
|
|
|
struct MakeTupleReturnType {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct MakeTupleReturnType<ReferenceWrapper<T>> {
|
|
|
|
using Type = T &;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct MakeTupleReturn {
|
|
|
|
using Type = typename MakeTupleReturnType<Decay<T>>::Type;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T>
|
|
|
|
inline Tuple<typename detail::MakeTupleReturn<T>::Type...>
|
|
|
|
make_tuple(T &&...t) {
|
|
|
|
return Tuple<typename detail::MakeTupleReturn<T>::Type...>(forward<T>(t)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* forward as tuple */
|
|
|
|
|
|
|
|
template<typename ...T>
|
|
|
|
inline Tuple<T &&...> forward_as_tuple(T &&...t) {
|
|
|
|
return Tuple<T &&...>(forward<T>(t)...);
|
|
|
|
}
|
|
|
|
|
2015-07-11 21:05:02 +00:00
|
|
|
/* tuple relops */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<Size I>
|
|
|
|
struct TupleEqual {
|
|
|
|
template<typename T, typename U>
|
|
|
|
bool operator()(const T &x, const U &y) {
|
|
|
|
return TupleEqual<I - 1>()(x, y) && (get<I>(x) == get<I>(y));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct TupleEqual<0> {
|
|
|
|
template<typename T, typename U>
|
|
|
|
bool operator()(const T &, const U &) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator==(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return detail::TupleEqual<sizeof...(T)>(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator!=(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return !(x == y);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<Size I>
|
|
|
|
struct TupleLess {
|
|
|
|
template<typename T, typename U>
|
|
|
|
bool operator()(const T &x, const U &y) {
|
2015-08-01 17:34:53 +00:00
|
|
|
constexpr Size J = TupleSize<T>::value - I;
|
2015-07-11 21:05:02 +00:00
|
|
|
if (get<J>(x) < get<J>(y)) return true;
|
|
|
|
if (get<J>(y) < get<J>(x)) return false;
|
|
|
|
return TupleLess<I - 1>()(x, y);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct TupleLess<0> {
|
|
|
|
template<typename T, typename U>
|
|
|
|
bool operator()(const T &, const U &) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator<(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return detail::TupleLess<sizeof...(T)>(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator>(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return y < x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator<=(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return !(y < x);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
|
|
|
inline bool operator>=(const Tuple<T...> &x, const Tuple<U...> &y) {
|
|
|
|
return !(x < y);
|
|
|
|
}
|
|
|
|
|
2015-07-11 21:24:36 +00:00
|
|
|
/* uses alloc */
|
|
|
|
|
|
|
|
template<typename ...T, typename A>
|
|
|
|
struct UsesAllocator<Tuple<T...>, A>: True {};
|
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
#endif
|