Skip to content

Instantly share code, notes, and snippets.

@ZhekehZ
Last active September 1, 2020 12:24
Show Gist options
  • Save ZhekehZ/8505cd2993a9a98add600f8a8df5b162 to your computer and use it in GitHub Desktop.
Save ZhekehZ/8505cd2993a9a98add600f8a8df5b162 to your computer and use it in GitHub Desktop.
Returns the number of elements in the structure (type) that are applicable for structured binding declaration (https://en.cppreference.com/w/cpp/language/structured_binding). On godbolt: https://godbolt.org/z/Px3Pbb
#include <utility>
#include <tuple>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/control/if.hpp>
#define BINDERS_LIMIT 256 // Number of binders must be less than BINDERS_LIMIT
template <typename... Ts> struct overloads : Ts... { using Ts::operator()...; };
template <typename... Ts> overloads(Ts...) -> overloads<Ts...>;
template <typename Cls>
auto count_binders_ptr() noexcept {
#define DECL(z, n, d) char (*_##n)[n] = nullptr;
BOOST_PP_REPEAT(BINDERS_LIMIT, DECL, _)
#undef DECL
Cls * cls = nullptr;
#define DECL(z, n, d) BOOST_PP_COMMA_IF(n) _##n
#define LAM(n) , [&](auto && t) -> \
decltype(({auto && [BOOST_PP_REPEAT(n, DECL, int)] = t; _##n;})) \
{ return _##n; }
#define Z(...) [&](...) { return _0; }
#define LAMBDA_GENERATOR(z, n, d) BOOST_PP_IF(n, LAM, Z)(n)
return overloads { BOOST_PP_REPEAT(BINDERS_LIMIT, LAMBDA_GENERATOR, _) } (*cls);
#undef LAM
#undef DECL
#undef Z
#undef LAMBDA_GENERATOR
}
template <typename Cls>
static constexpr std::size_t n_bindings = sizeof(*count_binders_ptr<Cls>());
/// USAGE
using T0 = int;
struct T1 { char c; };
using T2 = std::pair<int, int>;
struct T3 { int x; int y; int z; };
using T10 = std::tuple<int, int, int, int, int, int, int, int, int, int>;
static_assert(n_bindings<T0> == 0);
static_assert(n_bindings<T1> == 1);
static_assert(n_bindings<T2> == 2);
static_assert(n_bindings<T3> == 3);
static_assert(n_bindings<T10> == 10);
@ZhekehZ
Copy link
Author

ZhekehZ commented Aug 30, 2020

Warning: there is a bug in gcc

g++-10 output:

<source>: In function 'auto count_binders_ptr()':

<source>:25:66: internal compiler error: in cp_parser_decomposition_declaration, at cp/parser.c:13984

   25 |                 decltype(({auto && [BOOST_PP_REPEAT(n, DECL, int)] = t; _##n;})) \

      |                                                                  ^

/celibs/boost_1_74_0/boost/preprocessor/control/iif.hpp:32:31: note: in expansion of macro 'LAM'

   32 | # define BOOST_PP_IIF_1(t, f) t

      |                               ^

/celibs/boost_1_74_0/boost/preprocessor/repetition/repeat.hpp:53:62: note: in expansion of macro 'LAMBDA_GENERATOR'

   53 | # define BOOST_PP_REPEAT_1_2(m, d) BOOST_PP_REPEAT_1_1(m, d) m(2, 1, d)

      |                                                              ^

Please submit a full bug report,

with preprocessed source if appropriate.

See <https://gcc.gnu.org/bugs/> for instructions.

Compiler returned: 1

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