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 */
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename ...T>
|
|
|
|
constexpr Size TupleSize<Tuple<T...>> = 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-07-31 19:40:25 +00:00
|
|
|
static_assert(
|
|
|
|
!IsReference<H>,
|
|
|
|
"attempt to default construct a reference element in a tuple"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 0>, A const &): p_value() {
|
2016-07-31 19:40:25 +00:00
|
|
|
static_assert(
|
|
|
|
!IsReference<H>,
|
|
|
|
"attempt to default construct a reference element in a tuple"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 1>, A const &a): p_value(allocator_arg, a) {
|
2016-07-31 19:40:25 +00:00
|
|
|
static_assert(
|
|
|
|
!IsReference<H>,
|
|
|
|
"attempt to default construct a reference element in a tuple"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 2>, A const &a): p_value(a) {
|
2016-07-31 19:40:25 +00:00
|
|
|
static_assert(
|
|
|
|
!IsReference<H>,
|
|
|
|
"attempt to default construct a reference element in a tuple"
|
|
|
|
);
|
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>
|
|
|
|
>>
|
2015-07-11 01:38:11 +00:00
|
|
|
explicit TupleLeaf(T &&t): p_value(forward<T>(t)) {
|
2016-07-31 19:40:25 +00:00
|
|
|
static_assert(
|
|
|
|
!IsReference<H> || (
|
|
|
|
IsLvalueReference<H> && (
|
|
|
|
IsLvalueReference<T> || IsSame<
|
|
|
|
RemoveReference<T>,
|
|
|
|
ReferenceWrapper<RemoveReference<H>>
|
|
|
|
>
|
|
|
|
)
|
|
|
|
) || (IsRvalueReference<H> && !IsLvalueReference<T>),
|
|
|
|
"attempt to construct a reference element in a tuple with an rvalue"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 0>, A const &, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_value(forward<T>(t))
|
|
|
|
{
|
|
|
|
static_assert(
|
|
|
|
!IsLvalueReference<H> || (
|
|
|
|
IsLvalueReference<H> && (
|
|
|
|
IsLvalueReference<T> || IsSame<
|
|
|
|
RemoveReference<T>,
|
|
|
|
ReferenceWrapper<RemoveReference<H>>
|
|
|
|
>
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"attempt to construct a reference element in a tuple with an rvalue"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 1>, A const &a, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_value(allocator_arg, a, forward<T>(t))
|
|
|
|
{
|
|
|
|
static_assert(
|
|
|
|
!IsLvalueReference<H> || (
|
|
|
|
IsLvalueReference<H> && (
|
|
|
|
IsLvalueReference<T> || IsSame<
|
|
|
|
RemoveReference<T>,
|
|
|
|
ReferenceWrapper<RemoveReference<H>>
|
|
|
|
>
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"attempt to construct a reference element in a tuple with an rvalue"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 2>, A const &a, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_value(forward<T>(t), a)
|
|
|
|
{
|
|
|
|
static_assert(
|
|
|
|
!IsLvalueReference<H> || (
|
|
|
|
IsLvalueReference<H> && (
|
|
|
|
IsLvalueReference<T> || IsSame<
|
|
|
|
RemoveReference<T>,
|
|
|
|
ReferenceWrapper<RemoveReference<H>>
|
|
|
|
>
|
|
|
|
)
|
|
|
|
),
|
|
|
|
"attempt to construct a reference element in a tuple with an rvalue"
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(TupleLeaf const &) = default;
|
2015-07-11 01:38:11 +00:00
|
|
|
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; }
|
2016-06-23 18:18:35 +00:00
|
|
|
H const &get() const { return p_value; }
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
private:
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf &operator=(TupleLeaf const &);
|
2015-07-11 01:38:11 +00:00
|
|
|
H p_value;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<Size I, typename H>
|
|
|
|
struct TupleLeaf<I, H, true>: private H {
|
|
|
|
constexpr TupleLeaf() {}
|
|
|
|
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 0>, A const &) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 1>, A const &a):
|
2016-07-31 19:40:25 +00:00
|
|
|
H(allocator_arg, a)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(Constant<int, 2>, A const &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>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>
|
|
|
|
explicit TupleLeaf(T &&t): H(forward<T>(t)) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 0>, A const &, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
H(forward<T>(t))
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 1>, A const &a, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
H(allocator_arg, a, forward<T>(t))
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit TupleLeaf(Constant<int, 2>, A const &a, T &&t):
|
2016-07-31 19:40:25 +00:00
|
|
|
H(forward<T>(t), a)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf(TupleLeaf const &) = default;
|
2015-07-11 01:38:11 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-07-02 03:56:23 +00:00
|
|
|
H &get() { return *static_cast<H *>(this); }
|
|
|
|
H const &get() const { return *static_cast<H const *>(this); }
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
private:
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleLeaf &operator=(TupleLeaf const &);
|
2015-07-11 01:38:11 +00:00
|
|
|
};
|
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
/* internal utils */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename ...A>
|
|
|
|
inline void tuple_swallow(A &&...) {}
|
|
|
|
|
2016-01-23 17:26:42 +00:00
|
|
|
template<bool ...A>
|
|
|
|
constexpr bool TupleAll = true;
|
|
|
|
|
|
|
|
template<bool B, bool ...A>
|
|
|
|
constexpr bool TupleAll<B, A...> = B && TupleAll<A...>;
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2016-01-20 18:42:29 +00:00
|
|
|
constexpr bool TupleAllDefaultConstructible = detail::Undefined<T>();
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool TupleAllDefaultConstructible<TupleTypes<A...>> =
|
|
|
|
TupleAll<IsDefaultConstructible<A>...>;
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* tuple implementation */
|
|
|
|
|
|
|
|
namespace detail {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename, typename ...>
|
|
|
|
struct TupleBase;
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<Size ...I, typename ...A>
|
|
|
|
struct TupleBase<TupleIndices<I...>, A...>: TupleLeaf<I, A>... {
|
|
|
|
constexpr TupleBase() {}
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
Size ...Ia, typename ...Aa, Size ...Ib,
|
|
|
|
typename ...Ab, typename ...T
|
|
|
|
>
|
|
|
|
explicit TupleBase(
|
|
|
|
TupleIndices<Ia...>, TupleTypes<Aa...>,
|
|
|
|
TupleIndices<Ib...>, TupleTypes<Ab...>, T &&...t
|
|
|
|
):
|
2015-07-11 01:38:11 +00:00
|
|
|
TupleLeaf<Ia, Aa>(forward<T>(t))...,
|
2016-07-31 19:40:25 +00:00
|
|
|
TupleLeaf<Ib, Ab>()...
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<
|
|
|
|
typename Alloc, Size ...Ia, typename ...Aa,
|
|
|
|
Size ...Ib, typename ...Ab, typename ...T
|
|
|
|
>
|
|
|
|
explicit TupleBase(
|
|
|
|
AllocatorArg, Alloc const &a,
|
|
|
|
TupleIndices<Ia...>, TupleTypes<Aa...>,
|
|
|
|
TupleIndices<Ib...>, TupleTypes<Ab...>, T &&...t
|
|
|
|
):
|
|
|
|
TupleLeaf<Ia, Aa>(
|
|
|
|
UsesAllocatorConstructor<Aa, Alloc, T>, a,
|
|
|
|
forward<T>(t)
|
|
|
|
)...,
|
2016-01-20 18:42:29 +00:00
|
|
|
TupleLeaf<Ib, Ab>(UsesAllocatorConstructor<Ab, Alloc>, a)...
|
2015-07-11 01:38:11 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T, typename = EnableIf<
|
2016-01-16 18:45:55 +00:00
|
|
|
TupleConstructible<T, Tuple<A...>>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>
|
|
|
|
TupleBase(T &&t):
|
|
|
|
TupleLeaf<I, A>(
|
|
|
|
forward<TupleElement<I, MakeTupleTypes<T>>>(get<I>(t))
|
|
|
|
)...
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename Alloc, typename T, typename = EnableIf<
|
2016-01-16 18:45:55 +00:00
|
|
|
TupleConvertible<T, Tuple<A...>>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>
|
|
|
|
TupleBase(AllocatorArg, Alloc const &a, T &&t):
|
|
|
|
TupleLeaf<I, A>(
|
|
|
|
UsesAllocatorConstructor<
|
|
|
|
A, Alloc, TupleElement<I, MakeTupleTypes<T>>
|
|
|
|
>, a, forward<TupleElement<I, MakeTupleTypes<T>>>(get<I>(t))
|
|
|
|
)...
|
2015-07-11 01:38:11 +00:00
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
EnableIf<TupleAssignable<T, Tuple<A...>>, TupleBase &> operator=(T &&t) {
|
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(
|
|
|
|
forward<TupleElement<I, MakeTupleTypes<T>>>(get<I>(t))
|
|
|
|
)...);
|
2015-07-11 01:38:11 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleBase(TupleBase const &) = default;
|
2015-07-11 01:38:11 +00:00
|
|
|
TupleBase(TupleBase &&) = default;
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
TupleBase &operator=(TupleBase const &t) {
|
2016-07-31 19:40:25 +00:00
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(
|
|
|
|
(static_cast<TupleLeaf<I, A> const &>(t)).get()
|
|
|
|
)...);
|
2015-07-11 01:38:11 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
TupleBase &operator=(TupleBase &&t) {
|
2016-07-31 19:40:25 +00:00
|
|
|
tuple_swallow(TupleLeaf<I, A>::operator=(
|
|
|
|
forward<A>((static_cast<TupleLeaf<I, A> &>(t)).get())
|
|
|
|
)...);
|
2015-07-11 01:38:11 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(TupleBase &t) {
|
2016-07-31 19:40:25 +00:00
|
|
|
tuple_swallow(
|
|
|
|
TupleLeaf<I, A>::swap(static_cast<TupleLeaf<I, A> &>(t))...
|
|
|
|
);
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
} /* 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>
|
2016-06-23 18:18:35 +00:00
|
|
|
friend TupleElement<I, Tuple<T...>> const &get(Tuple<T...> const &);
|
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
|
|
|
|
2016-05-02 17:21:54 +00:00
|
|
|
template<Size I, typename ...T>
|
2016-06-23 18:18:35 +00:00
|
|
|
friend TupleElement<I, Tuple<T...>> const &&get(Tuple<T...> const &&);
|
2016-05-02 17:21:54 +00:00
|
|
|
|
2015-07-11 01:38:11 +00:00
|
|
|
public:
|
|
|
|
template<bool D = true, typename = EnableIf<
|
2016-01-20 18:42:29 +00:00
|
|
|
detail::TupleAll<(D && IsDefaultConstructible<A>)...>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>
|
|
|
|
Tuple() {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit Tuple(A const &...t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_base(
|
|
|
|
detail::MakeTupleIndices<sizeof...(A)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A)>(),
|
|
|
|
detail::MakeTupleIndices<0>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, 0>(), t...
|
|
|
|
)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename Alloc>
|
2016-06-23 18:18:35 +00:00
|
|
|
Tuple(AllocatorArg, Alloc const &a, A const &...t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_base(
|
|
|
|
allocator_arg, a,
|
2015-07-11 01:38:11 +00:00
|
|
|
detail::MakeTupleIndices<sizeof...(A)>(),
|
|
|
|
detail::MakeTupleTypes<Tuple, sizeof...(A)>(),
|
|
|
|
detail::MakeTupleIndices<0>(),
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<Tuple, 0>(), t...
|
|
|
|
)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename ...T, EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-16 18:45:55 +00:00
|
|
|
> &&
|
2015-07-11 01:38:11 +00:00
|
|
|
detail::TupleAllDefaultConstructible<
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-20 18:42:29 +00:00
|
|
|
>, bool
|
2015-07-11 01:38:11 +00:00
|
|
|
> = true>
|
|
|
|
Tuple(T &&...t):
|
2016-07-31 19:40:25 +00:00
|
|
|
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)...
|
|
|
|
)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename ...T, EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConstructible<
|
|
|
|
Tuple<T...>,
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-16 18:45:55 +00:00
|
|
|
> &&
|
2015-07-11 01:38:11 +00:00
|
|
|
!detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-16 18:45:55 +00:00
|
|
|
> &&
|
2015-07-11 01:38:11 +00:00
|
|
|
detail::TupleAllDefaultConstructible<
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-20 18:42:29 +00:00
|
|
|
>, bool
|
2015-07-11 01:38:11 +00:00
|
|
|
> = true>
|
|
|
|
Tuple(T &&...t):
|
2016-07-31 19:40:25 +00:00
|
|
|
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)...
|
|
|
|
)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename Alloc, typename ...T, typename = EnableIf<
|
|
|
|
(sizeof...(T) <= sizeof...(A)) &&
|
|
|
|
detail::TupleConvertible<
|
|
|
|
Tuple<T...>,
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple,
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-16 18:45:55 +00:00
|
|
|
> &&
|
2015-07-11 01:38:11 +00:00
|
|
|
detail::TupleAllDefaultConstructible<
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::MakeTupleTypes<
|
|
|
|
Tuple, sizeof...(A),
|
|
|
|
(sizeof...(T) < sizeof...(A)) ? sizeof...(T) : sizeof...(A)
|
2015-07-11 01:38:11 +00:00
|
|
|
>
|
2016-01-20 18:42:29 +00:00
|
|
|
>
|
2016-06-23 18:18:35 +00:00
|
|
|
>> Tuple(AllocatorArg, Alloc const &a, T &&...t):
|
2016-07-31 19:40:25 +00:00
|
|
|
p_base(
|
|
|
|
allocator_arg, a, 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)...
|
|
|
|
)
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, EnableIf<
|
2016-01-16 18:45:55 +00:00
|
|
|
detail::TupleConvertible<T, Tuple>, bool
|
2016-07-31 19:40:25 +00:00
|
|
|
> = true>
|
|
|
|
Tuple(T &&t): p_base(forward<T>(t)) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename T, EnableIf<
|
2016-01-16 18:45:55 +00:00
|
|
|
detail::TupleConstructible<T, Tuple> &&
|
|
|
|
!detail::TupleConvertible<T, Tuple>, bool
|
2016-07-31 19:40:25 +00:00
|
|
|
> = true>
|
|
|
|
Tuple(T &&t): p_base(forward<T>(t)) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
|
|
|
template<typename Alloc, typename T, typename = EnableIf<
|
2016-01-16 18:45:55 +00:00
|
|
|
detail::TupleConvertible<T, Tuple>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>
|
|
|
|
Tuple(AllocatorArg, Alloc const &a, T &&t):
|
|
|
|
p_base(allocator_arg, a, forward<T>(t))
|
|
|
|
{}
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2016-01-16 18:45:55 +00:00
|
|
|
template<typename T, typename = EnableIf<detail::TupleAssignable<T, Tuple>>>
|
|
|
|
Tuple &operator=(T &&t) {
|
2015-07-11 01:38:11 +00:00
|
|
|
p_base.operator=(forward<T>(t));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(Tuple &t) {
|
|
|
|
p_base.swap(t.p_base);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> class Tuple<> {
|
|
|
|
public:
|
|
|
|
constexpr Tuple() {}
|
2016-06-23 18:18:35 +00:00
|
|
|
template<typename A> Tuple(AllocatorArg, A const &) {}
|
|
|
|
template<typename A> Tuple(AllocatorArg, A const &, Tuple const &) {}
|
2015-07-11 01:38:11 +00:00
|
|
|
void swap(Tuple &) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* get */
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
|
|
|
inline TupleElement<I, Tuple<A...>> &get(Tuple<A...> &t) {
|
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
2016-07-02 03:56:23 +00:00
|
|
|
return static_cast<detail::TupleLeaf<I, Type> &>(t.p_base).get();
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline TupleElement<I, Tuple<A...>> const &get(Tuple<A...> const &t) {
|
2015-07-11 01:38:11 +00:00
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
2016-07-02 03:56:23 +00:00
|
|
|
return static_cast<detail::TupleLeaf<I, Type> const &>(t.p_base).get();
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
|
|
|
inline TupleElement<I, Tuple<A...>> &&get(Tuple<A...> &&t) {
|
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
2016-07-02 03:56:23 +00:00
|
|
|
return static_cast<Type &&>(
|
|
|
|
static_cast<detail::TupleLeaf<I, Type> &&>(t.p_base).get());
|
2016-05-02 17:21:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<Size I, typename ...A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline TupleElement<I, Tuple<A...>> const &&get(Tuple<A...> const &&t) {
|
2016-05-02 17:21:54 +00:00
|
|
|
using Type = TupleElement<I, Tuple<A...>>;
|
2016-07-02 03:56:23 +00:00
|
|
|
return static_cast<Type const &&>(
|
|
|
|
static_cast<detail::TupleLeaf<I, Type> const &&>(t.p_base).get());
|
2015-07-11 01:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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>
|
2016-06-23 18:18:35 +00:00
|
|
|
Ignore const &operator=(T &&) const { return *this; }
|
2015-07-11 02:26:57 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
static detail::Ignore const ignore = detail::Ignore();
|
2015-07-11 02:26:57 +00:00
|
|
|
|
|
|
|
/* 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>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline Tuple<typename detail::MakeTupleReturn<T>::Type...> make_tuple(T &&...t) {
|
2015-07-11 02:26:57 +00:00
|
|
|
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>
|
2016-06-23 18:18:35 +00:00
|
|
|
bool operator()(T const &x, U const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return TupleEqual<I - 1>()(x, y) && (get<I>(x) == get<I>(y));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct TupleEqual<0> {
|
|
|
|
template<typename T, typename U>
|
2016-06-23 18:18:35 +00:00
|
|
|
bool operator()(T const &, U const &) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator==(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return detail::TupleEqual<sizeof...(T)>(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator!=(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return !(x == y);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<Size I>
|
|
|
|
struct TupleLess {
|
|
|
|
template<typename T, typename U>
|
2016-06-23 18:18:35 +00:00
|
|
|
bool operator()(T const &x, U const &y) {
|
2016-01-19 19:14:02 +00:00
|
|
|
constexpr Size J = TupleSize<T> - 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>
|
2016-06-23 18:18:35 +00:00
|
|
|
bool operator()(T const &, U const &) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator<(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return detail::TupleLess<sizeof...(T)>(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator>(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return y < x;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator<=(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return !(y < x);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ...T, typename ...U>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline bool operator>=(Tuple<T...> const &x, Tuple<U...> const &y) {
|
2015-07-11 21:05:02 +00:00
|
|
|
return !(x < y);
|
|
|
|
}
|
|
|
|
|
2015-07-11 21:24:36 +00:00
|
|
|
/* uses alloc */
|
|
|
|
|
|
|
|
template<typename ...T, typename A>
|
2016-01-20 18:42:29 +00:00
|
|
|
constexpr bool UsesAllocator<Tuple<T...>, A> = true;
|
2015-07-11 21:24:36 +00:00
|
|
|
|
2016-09-11 12:08:56 +00:00
|
|
|
/* piecewise pair stuff */
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
template<typename ...A1, typename ...A2, Size ...I1, Size ...I2>
|
|
|
|
Pair<T, U>::Pair(
|
|
|
|
PiecewiseConstruct, Tuple<A1...> &fa, Tuple<A2...> &sa,
|
|
|
|
detail::TupleIndices<I1...>, detail::TupleIndices<I2...>
|
|
|
|
):
|
|
|
|
first(forward<A1>(get<I1>(fa))...), second(forward<A2>(get<I2>(sa))...)
|
|
|
|
{}
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename U>
|
|
|
|
template<typename ...A1, typename ...A2, Size ...I1, Size ...I2>
|
|
|
|
CompressedPairBase<T, U, 0>::CompressedPairBase(
|
|
|
|
PiecewiseConstruct, Tuple<A1...> &fa, Tuple<A2...> &sa,
|
|
|
|
detail::TupleIndices<I1...>, detail::TupleIndices<I2...>
|
|
|
|
):
|
|
|
|
p_first(forward<A1>(get<I1>(fa))...),
|
|
|
|
p_second(forward<A2>(get<I2>(sa))...)
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
template<typename ...A1, typename ...A2, Size ...I1, Size ...I2>
|
|
|
|
CompressedPairBase<T, U, 1>::CompressedPairBase(
|
|
|
|
PiecewiseConstruct, Tuple<A1...> &fa, Tuple<A2...> &sa,
|
|
|
|
detail::TupleIndices<I1...>, detail::TupleIndices<I2...>
|
|
|
|
):
|
|
|
|
T(forward<A1>(get<I1>(fa))...),
|
|
|
|
p_second(forward<A2>(get<I2>(sa))...)
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
template<typename ...A1, typename ...A2, Size ...I1, Size ...I2>
|
|
|
|
CompressedPairBase<T, U, 2>::CompressedPairBase(
|
|
|
|
PiecewiseConstruct, Tuple<A1...> &fa, Tuple<A2...> &sa,
|
|
|
|
detail::TupleIndices<I1...>, detail::TupleIndices<I2...>
|
|
|
|
):
|
|
|
|
U(forward<A2>(get<I2>(sa))...),
|
|
|
|
p_first(forward<A1>(get<I1>(fa))...)
|
|
|
|
{}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
template<typename ...A1, typename ...A2, Size ...I1, Size ...I2>
|
|
|
|
CompressedPairBase<T, U, 3>::CompressedPairBase(
|
|
|
|
PiecewiseConstruct, Tuple<A1...> &fa, Tuple<A2...> &sa,
|
|
|
|
detail::TupleIndices<I1...>, detail::TupleIndices<I2...>
|
|
|
|
):
|
|
|
|
T(forward<A1>(get<I1>(fa))...),
|
|
|
|
U(forward<A2>(get<I2>(sa))...)
|
|
|
|
{}
|
|
|
|
} /* namespace detail */
|
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-07-11 01:38:11 +00:00
|
|
|
|
2016-02-07 21:17:15 +00:00
|
|
|
#endif
|