Skip to content

Instantly share code, notes, and snippets.

/tuple.h Secret

Created October 11, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/0d777cd07c516bc48cf3 to your computer and use it in GitHub Desktop.
Save anonymous/0d777cd07c516bc48cf3 to your computer and use it in GitHub Desktop.
template <typename T1, typename T2> struct pair;
template <typename T, typename... OtherArgs>
struct tuple_helper: tuple_helper<OtherArgs...> {
T t;
tuple_helper() = default;
tuple_helper(const T & arg, const OtherArgs &... args) noexcept(
noexcept(T(arg)) && noexcept(tuple_helper<OtherArgs...>(args...))
): t(arg), tuple_helper<OtherArgs...>(args...) {}
tuple_helper(T&& arg, OtherArgs&&... args) noexcept(
noexcept(T(move(arg))) &&
noexcept(tuple_helper<OtherArgs...>(move(args)...))
): t(move(arg)), tuple_helper<OtherArgs...>(move(args)...) {}
template <typename Arg, typename... Args>
tuple_helper(const tuple_helper<Arg, Args...> &th) noexcept(
noexcept(T(th.t)) &&
noexcept(tuple_helper<OtherArgs...>(
static_cast<const tuple_helper<Args...> &>(th)))
): t(th.t), tuple_helper<OtherArgs...>(
static_cast<const tuple_helper<Args...> &>(th)) {}
template <typename Arg, typename... Args>
tuple_helper(tuple_helper<Arg, Args...> &&th) noexcept(
noexcept(T(move(th.t))) &&
noexcept(tuple_helper<OtherArgs...>(
static_cast<tuple_helper<Args...> &&>(th)))
): t(move(th.t)),
tuple_helper<OtherArgs...>(static_cast<tuple_helper<Args...> &&>(th)) {}
tuple_helper(const tuple_helper &th) noexcept(
noexcept(T(th.t)) &&
noexcept(tuple_helper<OtherArgs...>(
static_cast<const tuple_helper<OtherArgs...> &>(th)))
): t(th.t), tuple_helper<OtherArgs...>(
static_cast<const tuple_helper<OtherArgs...> &>(th)) {}
tuple_helper(tuple_helper &&th) noexcept(
noexcept(T(move(th.t))) &&
noexcept(tuple_helper<OtherArgs...>(
static_cast<tuple_helper<OtherArgs...> &&>(th)))
): t(move(th.t)), tuple_helper<OtherArgs...>(
static_cast<tuple_helper<OtherArgs...> &&>(th)) {}
tuple_helper &operator=(const tuple_helper &th) noexcept(
noexcept(t = th.t) &&
noexcept(tuple_helper<OtherArgs...>::operator=(
static_cast<const tuple_helper<OtherArgs...> &>(th))))
{
t = th.t;
tuple_helper<OtherArgs...>::operator=(
static_cast<const tuple_helper<OtherArgs...> &>(th));
return *this;
}
tuple_helper &operator=(tuple_helper &&th) noexcept(
noexcept(t = move(th.t)) &&
noexcept(tuple_helper<OtherArgs...>::operator=(
static_cast<tuple_helper<OtherArgs...> &&>(th))))
{
t = move(th.t);
tuple_helper<OtherArgs...>::operator=(
static_cast<tuple_helper<OtherArgs...> &&>(th));
return *this;
}
template <typename Other, typename... Others>
tuple_helper &operator=(const tuple_helper<Other, Others...> &th)
noexcept(noexcept(t = th.t) &&
noexcept(tuple_helper<OtherArgs...>::operator=(
static_cast<const tuple_helper<Others...> &>(th))))
{
t = th.t;
tuple_helper<OtherArgs...>::operator=(
static_cast<const tuple_helper<Others...> &>(th));
return *this;
}
template <typename Other, typename... Others>
tuple_helper &operator=(tuple_helper<Other, Others...> &&th)
noexcept(noexcept(t = move(th.t)) &&
noexcept(tuple_helper<OtherArgs...>::operator=(
static_cast<tuple_helper<Others...> &&>(th))))
{
t = move(th.t);
tuple_helper<OtherArgs...>::operator=(
static_cast<tuple_helper<Others...> &&>(th));
return *this;
}
void swap(tuple_helper &th) noexcept(
noexcept(swap(t, th.t)) &&
noexcept(tuple_helper<OtherArgs...>::swap(
static_cast<tuple_helper &>(th))))
{
swap(t, th.t);
tuple_helper<OtherArgs...>::swap(th);
}
};
template <typename T1, typename T2>
struct tuple_helper<T1, T2> {
T1 t1;
T1 t2;
tuple_helper() = default;
tuple_helper(const T1 & o1, const T2& o2)
noexcept(noexcept(T1(o1)) && noexcept(T2(o2))): t1(o1), t2(o2) {}
tuple_helper(T1&& o1, T2&& o2)
noexcept(noexcept(T1(move(o1))) && noexcept(T2(move(o2)))):
t1(move(o1)), t2(move(o2)) {}
template <typename Other1, typename Other2>
tuple_helper(const tuple_helper<Other1, Other2> &th)
noexcept(noexcept(T1(th.t1)) && noexcept(T2(th.t2))):
t1(th.t1), t2(th.t2) {}
template <typename Other1, typename Other2>
tuple_helper(tuple_helper<Other1, Other2> &&th)
noexcept(noexcept(T1(move(th.t1))) && noexcept(T2(move(th.t2)))):
t1(move(th.t1)), t2(move(th.t2)) {}
template <typename Other1, typename Other2>
explicit tuple_helper(const pair<Other1, Other2> &);
template <typename Other1, typename Other2>
explicit tuple_helper(pair<Other1, Other2> &&);
template <typename Other1, typename Other2>
tuple_helper &operator=(const pair<Other1, Other2> &);
template <typename Other1, typename Other2>
tuple_helper &operator=(pair<Other1, Other2> &&);
tuple_helper(const tuple_helper &th)
noexcept(noexcept(T1(th.t1)) && noexcept(T2(th.t2))):
t1(th.t1), t2(th.t2) {}
tuple_helper(tuple_helper &&th)
noexcept(noexcept(T1(move(th.t1))) && noexcept(T2(move(th.t2)))):
t1(move(th.t1)), t2(move(th.t2)) {}
tuple_helper &operator=(const tuple_helper &th)
noexcept(noexcept(t1 = th.t1) && noexcept(th = th.t2))
{
t1 = th.t1;
t2 = th.t2;
return *this;
}
tuple_helper &operator=(tuple_helper &&th)
noexcept(noexcept(t1 = move(th.t1)) && noexcept(t2 = move(th.t2)))
{
t1 = move(th.t1);
t2 = move(th.t2);
return *this;
}
template <typename Other1, typename Other2>
tuple_helper &operator=(const tuple_helper<Other1, Other2> &th)
noexcept(noexcept(t1 = th.t1) && noexcept(th = th.t2))
{
t1 = th.t1;
t2 = th.t2;
return *this;
}
template <typename Other1, typename Other2>
tuple_helper &operator=(tuple_helper<Other1, Other2> &&th)
noexcept(noexcept(t1 = move(th.t1)) && noexcept(t2 = move(th.t2)))
{
t1 = move(th.t1);
t2 = move(th.t2);
return *this;
}
void swap(tuple_helper &th) noexcept(
noexcept(swap(t1, th.t1)) && noexcept(swap(t2, th.t2)))
{
swap(t1, th.t1);
swap(t2, th.t2);
}
};
template <typename T>
struct tuple_helper<T> {
T t;
tuple_helper() = default;
explicit
tuple_helper(const T & o) noexcept(noexcept(T(o))): t(o) {}
explicit
tuple_helper(T&& o) noexcept(noexcept(T(move(o)))): t(move(o)) {}
template <typename Other>
tuple_helper(const tuple_helper<Other> &th)
noexcept(noexcept(T(th.t))): t(th.t) {}
template <typename Other>
tuple_helper(tuple_helper<Other> &&th)
noexcept(noexcept(T(move(th.t)))): t(move(th.t)) {}
tuple_helper(const tuple_helper &th)
noexcept(noexcept(T(th.t))): t(th.t) {}
tuple_helper(tuple_helper &&th)
noexcept(noexcept(T(move(th.t)))): t(move(th.t)) {}
tuple_helper &operator=(const tuple_helper &th)
noexcept(noexcept(t = th.t))
{
t = th.t;
return *this;
}
tuple_helper &operator=(tuple_helper &&th)
noexcept(noexcept(t = move(th.t)))
{
t = move(th.t);
return *this;
}
template <typename Other>
tuple_helper &operator=(const tuple_helper<Other> &th)
noexcept(noexcept(t = th.t))
{
t = th.t;
return *this;
}
template <typename Other>
tuple_helper &operator=(tuple_helper<Other> &&th)
noexcept(noexcept(t = move(th.t)))
{
t = move(th.t);
return *this;
}
void swap(tuple_helper &th) noexcept(noexcept(swap(t, th.t)))
{
swap(t, th.t);
}
};
template <typename... Args>
struct tuple: tuple_helper<Args...> {
tuple() = default;
template <typename... OtherArgs> explicit
tuple(OtherArgs&&... args) noexcept(noexcept(
tuple_helper<Args...>(forward<OtherArgs>(args)...))):
tuple_helper<Args...>(forward<OtherArgs>(args)...) {}
template <typename... OtherArgs> explicit
tuple(const tuple<OtherArgs...> &ot)
noexcept(noexcept(tuple_helper<Args...>(ot))):
tuple_helper<Args...>(ot) {}
template <typename... OtherArgs> explicit
tuple(tuple<OtherArgs...> &&ot)
noexcept(noexcept(tuple_helper<Args...>(move(ot)))):
tuple_helper<Args...>(move(ot)) {}
template <typename Other1, typename Other2> explicit
tuple(const pair<Other1, Other2> &p) noexcept(noexcept(
tuple_helper<Args...>(p))):
tuple_helper<Args...>(p) {}
template <typename Other1, typename Other2> explicit
tuple(pair<Other1, Other2> &&p) noexcept(noexcept(
tuple_helper<Args...>(move(p)))):
tuple_helper<Args...>(move(p)) {}
tuple(const tuple &) = default;
tuple(tuple &&) = default;
tuple &operator=(const tuple &) = default;
tuple &operator=(tuple &&) = default;
template <typename Other1, typename Other2>
tuple &operator=(pair<Other1, Other2> &&p)
noexcept(noexcept(tuple_helper<Args...>::operator=(move(p))))
{
tuple_helper<Args...>::operator=(move(p));
return *this;
}
void swap(tuple &t) noexcept(noexcept(tuple_helper<Args...>::swap(t)))
{
tuple_helper<Args...>::swap(t);
}
};
//!下面是get
template <size_t N>
struct tuple_helper_get {
template <typename T, typename... Args> static
auto get_ref(tuple_helper<T, Args...> &t) noexcept
-> decltype(tuple_helper_get<N - 1>::get_ref
(static_cast<tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<N - 1>::get_ref(
static_cast<tuple_helper<Args...> &>(t));
}
template <typename T, typename... Args> static
auto get_ref(tuple_helper<T, Args...> &&t) noexcept
-> decltype(tuple_helper_get<N - 1>::get_ref
(static_cast<tuple_helper<Args...> &&>(t)))
{
return tuple_helper_get<N - 1>::get_ref(
static_cast<tuple_helper<Args...> &&>(t));
}
template <typename T, typename... Args> static
auto get_ref(const tuple_helper<T, Args...> &t) noexcept
-> decltype(tuple_helper_get<N - 1>::get_ref
(static_cast<const tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<N - 1>::get_ref(
static_cast<const tuple_helper<Args...> &>(t));
}
};
template <>
struct tuple_helper_get<0> {
template <typename T> static
T &&get_ref(T &&t) noexcept
{
return forward<T>(t);
}
template <typename T> static
T &get_ref(tuple_helper<T> &t) noexcept
{
return t.t;
}
template <typename T> static
T &&get_ref(tuple_helper<T> &&t) noexcept
{
return forward<T>(t.t);
}
template <typename T> static
auto get_ref(const tuple_helper<T> &t) noexcept
-> typename add_const<T>::type
{
return t.t;
}
template <typename T1, typename T2> static
T1 &get_ref(tuple_helper<T1, T2> &t) noexcept
{
return t.t1;
}
template <typename T1, typename T2> static
T1 &&get_ref(tuple_helper<T1, T2> &&t) noexcept
{
return forward<T1>(t.t1);
}
template <typename T1, typename T2> static
auto get_ref(const tuple_helper<T1, T2> &t) noexcept
-> typename add_const<T1>::type
{
return t.t1;
}
template <typename T, typename... Args> static
T &get_ref(tuple_helper<T, Args...> &t) noexcept
{
return t.t;
}
template <typename T, typename... Args> static
T &&get_ref(tuple_helper<T, Args...> &&t) noexcept
{
return forward<T>(t.t);
}
template <typename T, typename... Args> static
auto get_ref(const tuple_helper<T, Args...> &t) noexcept
-> typename add_const<T>::type
{
return t.t;
}
};
template <>
struct tuple_helper_get<1> {
template <typename T1, typename T2> static
T2 &get_ref(tuple_helper<T1, T2> &t) noexcept
{
return t.t2;
}
template <typename T1, typename T2> static
T2 &&get_ref(tuple_helper<T1, T2> &&t) noexcept
{
return forward<T2>(t.t2);
}
template <typename T1, typename T2> static
auto get_ref(const tuple_helper<T1, T2> &t) noexcept
-> typename add_const<T2>::type
{
return t.t2;
}
template <typename T, typename... Args> static
auto get_ref(tuple_helper<T, Args...> &t) noexcept
-> decltype(tuple_helper_get<0>::get_ref
(static_cast<tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<0>::get_ref(
static_cast<tuple_helper<Args...> &>(t));
}
template <typename T, typename... Args> static
auto get_ref(tuple_helper<T, Args...> &&t) noexcept
-> decltype(tuple_helper_get<0>::get_ref
(static_cast<tuple_helper<Args...> &&>(t)))
{
return tuple_helper_get<0>::get_ref(
static_cast<tuple_helper<Args...> &&>(t));
}
template <typename T, typename... Args> static
auto get_ref(const tuple_helper<T, Args...> &t) noexcept
-> decltype(tuple_helper_get<0>::get_ref
(static_cast<const tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<0>::get_ref(
static_cast<const tuple_helper<Args...> &>(t));
}
};
template <size_t N, typename T>
auto get(T&& t) noexcept
-> decltype(tuple_helper_get<N>::get_ref(t))
{
return tuple_helper_get<N>::get_ref(t);
}
template <size_t N, typename... Args>
auto get(tuple<Args...> &t) noexcept
-> decltype(tuple_helper_get<N>::get_ref
(static_cast<tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<N>::get_ref(
static_cast<tuple_helper<Args...> &>(t));
}
template <size_t N, typename... Args>
auto get(tuple<Args...> &&t) noexcept
-> decltype(tuple_helper_get<N>::get_ref
(static_cast<tuple_helper<Args...> &&>(t)))
{
return tuple_helper_get<N>::get_ref(
static_cast<tuple_helper<Args...> &&>(t));
}
template <size_t N, typename... Args>
auto get(const tuple<Args...> &t) noexcept
-> decltype(tuple_helper_get<N>::get_ref
(static_cast<const tuple_helper<Args...> &>(t)))
{
return tuple_helper_get<N>::get_ref(
static_cast<const tuple_helper<Args...> &>(t));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment