Skip to content

Instantly share code, notes, and snippets.

@tomilov
Last active January 3, 2017 22:06
Show Gist options
  • Save tomilov/0cf10f110a8e1a0b486603bba500640a to your computer and use it in GitHub Desktop.
Save tomilov/0cf10f110a8e1a0b486603bba500640a to your computer and use it in GitHub Desktop.
#include <type_traits>
#include <utility>
#include <tuple>
struct filler { template< typename type > operator type (); };
template< typename aggregate,
typename index_sequence = std::index_sequence<>,
typename = void >
struct aggregate_arity
: index_sequence
{
};
template< typename aggregate,
std::size_t ...indices >
struct aggregate_arity< aggregate,
std::index_sequence< indices... >,
std::void_t< decltype(aggregate{(void(indices), std::declval< filler >())..., std::declval< filler >()}) > >
: aggregate_arity< aggregate,
std::index_sequence< indices..., sizeof...(indices) > >
{
};
template< std::size_t index, typename type >
constexpr
decltype(auto)
get(type & value) noexcept
{
constexpr std::size_t arity = aggregate_arity< std::remove_cv_t< type > >::size();
if constexpr (arity == 1) {
auto & [p1] = value;
if constexpr (index == 0) {
return (p1);
} else {
return;
}
} else if constexpr (arity == 2) {
auto & [p1, p2] = value;
if constexpr (index == 0) {
return (p1);
} else if constexpr (index == 1) {
return (p2);
} else {
return;
}
} else if constexpr (arity == 3) {
auto & [p1, p2, p3] = value;
if constexpr (index == 0) {
return (p1);
} else if constexpr (index == 1) {
return (p2);
} else if constexpr (index == 2) {
return (p3);
} else {
return;
}
} else /* extend it by yourself for higher arities */ {
return;
}
}
// main.cpp
#include <cstdlib>
#include <cassert>
namespace
{
using S = struct { int i; char c; bool b; };
S s{1, '2', true};
decltype(auto) i = get< 0 >(s);
decltype(auto) c = get< 1 >(s);
decltype(auto) b = get< 2 >(s);
static_assert(std::is_same< decltype(i), int & >{});
static_assert(std::is_same< decltype(c), char & >{});
static_assert(std::is_same< decltype(b), bool & >{});
static_assert(&i == &s.i);
static_assert(&c == &s.c);
static_assert(&b == &s.b);
}
int
main()
{
assert(i == 1);
assert(c == '2');
assert(b == true);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment