Last active
January 3, 2017 22:06
-
-
Save tomilov/0cf10f110a8e1a0b486603bba500640a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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