Skip to content

Instantly share code, notes, and snippets.

@talybin
Last active October 21, 2019 14:01
Show Gist options
  • Select an option

  • Save talybin/66cfa681ac82e13b26731b0d905c6c0d to your computer and use it in GitHub Desktop.

Select an option

Save talybin/66cfa681ac82e13b26731b0d905c6c0d to your computer and use it in GitHub Desktop.
Basic implementation of tuple
#pragma once
#include <utility>
// Basic implementation of tuple
template <class...>
struct tuple;
template <>
struct tuple<> { };
template <class T, class... Ts>
struct tuple<T, Ts...> : tuple<Ts...>
{
tuple() = default;
tuple(T&& val, Ts&&... rest)
: tuple<Ts...>(std::forward<Ts>(rest)...)
, value_(std::forward<T>(val))
{ }
T value_;
};
namespace detail
{
// Apply type properties (const, volatile, reference) of Src to Dst
template <class Src, class Dst>
using transcribe_const_t = std::conditional_t<
std::is_const_v<std::remove_reference_t<Src>>, std::add_const_t<Dst>, Dst>;
template <class Src, class Dst>
using transcribe_volatile_t = std::conditional_t<
std::is_volatile_v<std::remove_reference_t<Src>>, std::add_volatile_t<Dst>, Dst>;
template <class Src, class Dst>
using transcribe_cv_t = transcribe_const_t<Src, transcribe_volatile_t<Src, Dst>>;
template <class Src, class Dst>
using transcribe_lref_t = std::conditional_t<
std::is_lvalue_reference_v<Src>, Dst&, Dst>;
template <class Src, class Dst>
using transcribe_rref_t = std::conditional_t<
std::is_rvalue_reference_v<Src>, Dst&&, Dst>;
template <class Src, class Dst>
using transcribe_ref_t = transcribe_lref_t<Src, transcribe_rref_t<Src, Dst>>;
template <class Src, class Dst>
using transcribe_t = transcribe_ref_t<Src, transcribe_cv_t<Src, Dst>>;
// Just some testing
static_assert(std::is_same_v<transcribe_cv_t<const int&, double>, const double>);
static_assert(std::is_same_v<transcribe_ref_t<const int&, double>, double&>);
static_assert(std::is_same_v<transcribe_ref_t<const int&&, double>, double&&>);
static_assert(std::is_same_v<transcribe_t<const int&&, double>, const double&&>);
// Search tuple by type and return tuple base
template <class T, class Tuple>
struct tuple_element_base {
using type = tuple<>;
};
template <class T, class Tuple>
using tuple_element_base_t = typename tuple_element_base<T, Tuple>::type;
template <class T, class First, class... Rest>
struct tuple_element_base<T, tuple<First, Rest...>>
: std::conditional<
std::is_same_v<T, First>,
tuple<First, Rest...>,
tuple_element_base_t<T, tuple<Rest...>> >
{ };
}
// Find tuple element by index. Additional type
// included for tuple base.
template <size_t I, class Tuple>
struct tuple_element;
template <class First, class... Rest>
struct tuple_element<0, tuple<First, Rest...>> {
using type = First;
using tuple_type = tuple<First, Rest...>;
};
template <size_t I, class First, class... Rest>
struct tuple_element<I, tuple<First, Rest...>>
: tuple_element<I - 1, tuple<Rest...>>
{ };
template <size_t I, class Tuple>
using tuple_element_t = typename tuple_element<I, Tuple>::type;
// Get tuple value by index
template <size_t N, class Tuple>
inline constexpr decltype(auto) get(Tuple&& t) noexcept
{
using Base = typename tuple_element<N, std::decay_t<Tuple>>::tuple_type;
return std::forward<detail::transcribe_t<Tuple, Base>>(t).value_;
}
// Get tuple value by type
template <class T, class Tuple>
inline constexpr decltype(auto) get(Tuple&& t) noexcept
{
using Base = detail::tuple_element_base_t<T, std::decay_t<Tuple>>;
return std::forward<detail::transcribe_t<Tuple, Base>>(t).value_;
}
#include <iostream>
#include "basic_tuple_impl.hpp"
// Printer
template <class... Ts>
void print(const tuple<Ts...>& t)
{
((std::cout << get<Ts>(t) << ", "), ...) << '\n';
}
int main()
{
const tuple<int, std::string> tup(42, "test");
print(tup);
std::cout << "by index:\n";
std::cout << " first: " << get<0>(tup) << '\n';
std::cout << " second: " << get<1>(tup) << '\n';
std::cout << "by type:\n";
std::cout << " first: " << get<int>(tup) << '\n';
std::cout << " second: " << get<std::string>(tup) << '\n';
}
@talybin

talybin commented Oct 21, 2019

Copy link
Copy Markdown
Author
42, test, 
by index:
  first: 42
  second: test
by type:
  first: 42
  second: test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment