Skip to content

Instantly share code, notes, and snippets.

@mrange
Last active August 29, 2015 14:22
Show Gist options
  • Save mrange/b1333443279ecdbd9a14 to your computer and use it in GitHub Desktop.
Save mrange/b1333443279ecdbd9a14 to your computer and use it in GitHub Desktop.
C++14 tuple
#define COPY_MOVE(type) \
type (type const &) = default; \
type (type &&) = default; \
type & operator= (type const &) = default; \
type & operator= (type &&) = default;
template<std::size_t>
struct my_tuple_index
{
};
template<std::size_t idx, typename ... TTypes>
struct my_tuple_impl;
template<std::size_t idx>
struct my_tuple_impl<idx>
{
my_tuple_impl () = default;
COPY_MOVE (my_tuple_impl);
protected:
bool is_equal (my_tuple_impl const & ) const
{
return true;
}
inline void get_impl (my_tuple_index<idx>) const
{
}
inline void get_impl (my_tuple_index<idx>)
{
}
inline void set_impl ()
{
}
};
template<std::size_t idx, typename THead, typename ...TTail>
struct my_tuple_impl<idx, THead, TTail...> : my_tuple_impl<idx + 1U, TTail...>
{
using base_type = my_tuple_impl<idx + 1U, TTail...>;
my_tuple_impl ()
: head (THead ())
{
}
template<typename TH, typename ...TT>
my_tuple_impl (TH && head, TT && ...tail)
: base_type (std::forward<TT> (tail)...)
, head (std::forward<TH> (head))
{
}
COPY_MOVE (my_tuple_impl);
using base_type::get_impl;
using base_type::set_impl;
protected:
bool is_equal (my_tuple_impl const & o) const
{
return
head == o.head
&& base_type::is_equal (o);
}
inline THead const & get_impl (my_tuple_index<idx>) const
{
return head;
}
inline THead & get_impl (my_tuple_index<idx>)
{
return head;
}
inline void set_impl (my_tuple_index<idx>, THead const & h) const
{
head = h;
}
inline void set_impl (my_tuple_index<idx>, THead && h)
{
head = std::move (h);
}
private:
THead head;
};
template<typename ...TTypes>
struct my_tuple : my_tuple_impl<0U, TTypes...>
{
using base_type = my_tuple_impl<0U, TTypes...>;
my_tuple () = default;
template<typename ...Ts>
my_tuple (Ts && ...args)
: base_type (std::forward<Ts> (args)...)
{
constexpr auto esz = sizeof... (TTypes);
constexpr auto asz = sizeof... (Ts);
static_assert (esz == asz, "my_tuple .ctor invoked with wrong number of arguments");
}
COPY_MOVE (my_tuple);
constexpr std::size_t size () const
{
return sizeof... (TTypes);
}
bool operator== (my_tuple const & o) const
{
return base_type::is_equal (o);
}
template<std::size_t idx>
auto && get () const
{
return base_type::get_impl (my_tuple_index<idx> ());
}
template<std::size_t idx>
auto && get ()
{
return base_type::get_impl (my_tuple_index<idx> ());
}
template<std::size_t idx, typename T>
void set (T && v)
{
base_type::set_impl (my_tuple_index<idx> (), std::forward<T> (v));
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment