From 47e0f7f3350af052aca1ab66dcc335a3f8d432db Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 28 Jul 2016 17:16:23 +0100 Subject: [PATCH] Neater implementation of constexpr std::tuple for gcc 4.9 --- src/blackmisc/metaclassprivate.h | 53 +++++++++++++++++--------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/blackmisc/metaclassprivate.h b/src/blackmisc/metaclassprivate.h index b5a4cc373..013133d65 100644 --- a/src/blackmisc/metaclassprivate.h +++ b/src/blackmisc/metaclassprivate.h @@ -59,42 +59,45 @@ namespace BlackMisc using std::get; using std::make_tuple; #else // Own implementation of tuple, because the one in GCC 4.9 is not constexpr. - template - struct conslist; - - template - struct conslist + template + struct tuple_part { - constexpr conslist() {} - constexpr conslist(const Head &v) : m_obj(v) {} - constexpr const Head &get(std::integral_constant) const { return m_obj; } - Head m_obj; - }; - - template - struct conslist : public conslist - { - constexpr conslist() {} - constexpr conslist(const Head &v, const Tail &... vs) : conslist(vs...), m_obj(v) {} - constexpr const Head &get(std::integral_constant) const { return m_obj; } - using conslist::get; - Head m_obj; + constexpr tuple_part() {} + constexpr tuple_part(const T &element) : m_element(element) {} + T m_element; }; template - struct tuple + struct tuple_impl; + template + struct tuple_impl, Ts...> : public tuple_part... + { + constexpr tuple_impl() {} + constexpr tuple_impl(const Ts &... vs) : tuple_part(vs)... {} + }; + + template + struct tuple : public tuple_impl, Ts...> { constexpr tuple() {} - constexpr tuple(const Ts &... vs) : m_conslist(vs...) {} - conslist<0, Ts...> m_conslist; + constexpr tuple(const Ts &... vs) : tuple_impl, Ts...>(vs...) {} constexpr static size_t c_size = sizeof...(Ts); }; - template - struct tuple_size : public std::integral_constant {}; + template + constexpr decltype(auto) get_impl(tuple_part &part) { return (part.m_element); } + template + constexpr decltype(auto) get_impl(tuple_part &&part) { return std::move(part.m_element); } + template + constexpr decltype(auto) get_impl(const tuple_part &part) { return (part.m_element); } + template + constexpr decltype(auto) get_impl(const tuple_part &&part) { return std::move(part.m_element); } template - constexpr decltype(auto) get(T &&tuple) { return std::forward(tuple).m_conslist.get(std::integral_constant()); } + constexpr decltype(auto) get(T &&tuple) { return get_impl(std::forward(tuple)); } + + template + struct tuple_size : public std::integral_constant {}; template constexpr auto make_tuple(Ts &&... vs) { return tuple...>(std::forward(vs)...); }