Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NikolausDemmel/bb234c08aa04395b8b0b00d369bd2b4f to your computer and use it in GitHub Desktop.
Save NikolausDemmel/bb234c08aa04395b8b0b00d369bd2b4f to your computer and use it in GitHub Desktop.
visit_struct.hpp and visit_struct_intrisive.hpp merged for inclusion in compiler explorer; source: https://github.com/garbageslam/visit_struct/tree/0e853f45f61e8b0fb714aa6c92ed53fc60dc0dbf/include/visit_struct
// (C) Copyright 2015 - 2018 Christopher Beck
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef VISIT_STRUCT_HPP_INCLUDED
#define VISIT_STRUCT_HPP_INCLUDED
/***
* Provides a facility to declare a structure as "visitable" and apply a visitor
* to it. The list of members is a compile-time data structure, and there is no
* run-time overhead.
*/
#include <utility>
#include <type_traits>
// Library version
#define VISIT_STRUCT_VERSION_MAJOR 1
#define VISIT_STRUCT_VERSION_MINOR 0
#define VISIT_STRUCT_VERSION_PATCH 0
#define VISIT_STRUCT_STRING_HELPER(X) #X
#define VISIT_STRUCT_STRING(X) VISIT_STRUCT_STRING_HELPER(X)
#define VISIT_STRUCT_VERSION_STRING VISIT_STRUCT_STRING(VISIT_STRUCT_VERSION_MAJOR) "." VISIT_STRUCT_STRING(VISIT_STRUCT_VERSION_MINOR) "." VISIT_STRUCT_STRING(VISIT_STRUCT_VERSION_PATCH)
// For MSVC 2013 support, we put constexpr behind a define.
# ifndef VISIT_STRUCT_CONSTEXPR
# if (defined _MSC_VER) && (_MSC_VER <= 1800)
# define VISIT_STRUCT_CONSTEXPR
# else
# define VISIT_STRUCT_CONSTEXPR constexpr
# endif
# endif
// After C++14 the apply_visitor function can be constexpr.
// We target C++11, but such functions are tagged VISIT_STRUCT_CXX14_CONSTEXPR.
# ifndef VISIT_STRUCT_CXX14_CONSTEXPR
# if ((defined _MSC_VER) && (_MSC_VER <= 1900)) || (!defined __cplusplus) || (__cplusplus == 201103L)
# define VISIT_STRUCT_CXX14_CONSTEXPR
# else
# define VISIT_STRUCT_CXX14_CONSTEXPR constexpr
# endif
# endif
namespace visit_struct {
namespace traits {
// Primary template which is specialized to register a type
template <typename T, typename ENABLE = void>
struct visitable;
// Helper template which checks if a type is registered
template <typename T, typename ENABLE = void>
struct is_visitable : std::false_type {};
template <typename T>
struct is_visitable<T,
typename std::enable_if<traits::visitable<T>::value>::type>
: std::true_type {};
// Helper template which removes cv and reference from a type (saves some typing)
template <typename T>
struct clean {
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
};
template <typename T>
using clean_t = typename clean<T>::type;
// Mini-version of std::common_type (we only require C++11)
template <typename T, typename U>
struct common_type {
typedef decltype(true ? std::declval<T>() : std::declval<U>()) type;
};
} // end namespace traits
// Tag for tag dispatch
template <typename T>
struct type_c { using type = T; };
// Accessor type: function object encapsulating a pointer-to-member
template <typename MemPtr, MemPtr ptr>
struct accessor {
template <typename T>
VISIT_STRUCT_CONSTEXPR auto operator()(T && t) const -> decltype(std::forward<T>(t).*ptr) {
return std::forward<T>(t).*ptr;
}
};
//
// User-interface
//
// Return number of fields in a visitable struct
template <typename S>
VISIT_STRUCT_CONSTEXPR std::size_t field_count()
{
return traits::visitable<traits::clean_t<S>>::field_count;
}
template <typename S>
VISIT_STRUCT_CONSTEXPR std::size_t field_count(S &&) { return field_count<S>(); }
// apply_visitor (one struct instance)
template <typename S, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto apply_visitor(V && v, S && s) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
traits::visitable<traits::clean_t<S>>::apply(std::forward<V>(v), std::forward<S>(s));
}
// apply_visitor (two struct instances)
template <typename S1, typename S2, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto apply_visitor(V && v, S1 && s1, S2 && s2) ->
typename std::enable_if<
traits::is_visitable<
traits::clean_t<typename traits::common_type<S1, S2>::type>
>::value
>::type
{
using common_S = typename traits::common_type<S1, S2>::type;
traits::visitable<traits::clean_t<common_S>>::apply(std::forward<V>(v),
std::forward<S1>(s1),
std::forward<S2>(s2));
}
// for_each (Alternate syntax for apply_visitor, reverses order of arguments)
template <typename V, typename S>
VISIT_STRUCT_CXX14_CONSTEXPR auto for_each(S && s, V && v) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
traits::visitable<traits::clean_t<S>>::apply(std::forward<V>(v), std::forward<S>(s));
}
// for_each with two structure instances
template <typename S1, typename S2, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto for_each(S1 && s1, S2 && s2, V && v) ->
typename std::enable_if<
traits::is_visitable<
traits::clean_t<typename traits::common_type<S1, S2>::type>
>::value
>::type
{
using common_S = typename traits::common_type<S1, S2>::type;
traits::visitable<traits::clean_t<common_S>>::apply(std::forward<V>(v),
std::forward<S1>(s1),
std::forward<S2>(s2));
}
// Visit the types (visit_struct::type_c<...>) of the registered members
template <typename S, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto visit_types(V && v) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
traits::visitable<traits::clean_t<S>>::visit_types(std::forward<V>(v));
}
// Visit the member pointers (&S::a) of the registered members
template <typename S, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto visit_pointers(V && v) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
traits::visitable<traits::clean_t<S>>::visit_pointers(std::forward<V>(v));
}
// Visit the accessors (function objects) of the registered members
template <typename S, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto visit_accessors(V && v) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
traits::visitable<traits::clean_t<S>>::visit_accessors(std::forward<V>(v));
}
// Apply visitor (with no instances)
// This calls visit_pointers, for backwards compat reasons
template <typename S, typename V>
VISIT_STRUCT_CXX14_CONSTEXPR auto apply_visitor(V && v) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value
>::type
{
visit_struct::visit_pointers<S>(std::forward<V>(v));
}
// Get value by index (like std::get for tuples)
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get(S && s) ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value,
decltype(traits::visitable<traits::clean_t<S>>::get_value(std::integral_constant<int, idx>{}, std::forward<S>(s)))
>::type
{
return traits::visitable<traits::clean_t<S>>::get_value(std::integral_constant<int, idx>{}, std::forward<S>(s));
}
// Get name of field, by index
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_name() ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value,
decltype(traits::visitable<traits::clean_t<S>>::get_name(std::integral_constant<int, idx>{}))
>::type
{
return traits::visitable<traits::clean_t<S>>::get_name(std::integral_constant<int, idx>{});
}
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_name(S &&) -> decltype(get_name<idx, S>()) {
return get_name<idx, S>();
}
// Get member pointer, by index
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_pointer() ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value,
decltype(traits::visitable<traits::clean_t<S>>::get_pointer(std::integral_constant<int, idx>{}))
>::type
{
return traits::visitable<traits::clean_t<S>>::get_pointer(std::integral_constant<int, idx>{});
}
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_pointer(S &&) -> decltype(get_pointer<idx, S>()) {
return get_pointer<idx, S>();
}
// Get member accessor, by index
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_accessor() ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value,
decltype(traits::visitable<traits::clean_t<S>>::get_accessor(std::integral_constant<int, idx>{}))
>::type
{
return traits::visitable<traits::clean_t<S>>::get_accessor(std::integral_constant<int, idx>{});
}
template <int idx, typename S>
VISIT_STRUCT_CONSTEXPR auto get_accessor(S &&) -> decltype(get_accessor<idx, S>()) {
return get_accessor<idx, S>();
}
// Get type, by index
template <int idx, typename S>
struct type_at_s {
using type_c = decltype(traits::visitable<traits::clean_t<S>>::type_at(std::integral_constant<int, idx>{}));
using type = typename type_c::type;
};
template <int idx, typename S>
using type_at = typename type_at_s<idx, S>::type;
// Get name of structure
template <typename S>
VISIT_STRUCT_CONSTEXPR auto get_name() ->
typename std::enable_if<
traits::is_visitable<traits::clean_t<S>>::value,
decltype(traits::visitable<traits::clean_t<S>>::get_name())
>::type
{
return traits::visitable<traits::clean_t<S>>::get_name();
}
template <typename S>
VISIT_STRUCT_CONSTEXPR auto get_name(S &&) -> decltype(get_name<S>()) {
return get_name<S>();
}
/***
* To implement the VISITABLE_STRUCT macro, we need a map-macro, which can take
* the name of a macro and some other arguments, and apply that macro to each other argument.
*
* There are some techniques you can use within C preprocessor to accomplish this succinctly,
* by settng up "recursive" macros.
*
* But this can also cause it to give worse error messages when something goes wrong.
*
* We are now doing it in a more "dumb", bulletproof way which has the advantage that it is
* more portable and gives better error messages.
* For discussion see IMPLEMENTATION_NOTES.md
*
* The code below is based on a patch from Jarod42, and is now generated by a python script.
* The purpose of the generated code is to define VISIT_STRUCT_PP_MAP as described.
*/
/*** Generated code ***/
static VISIT_STRUCT_CONSTEXPR const int max_visitable_members = 69;
#define VISIT_STRUCT_EXPAND(x) x
#define VISIT_STRUCT_PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10,\
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,\
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30,\
_31, _32, _33, _34, _35, _36, _37, _38, _39, _40,\
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50,\
_51, _52, _53, _54, _55, _56, _57, _58, _59, _60,\
_61, _62, _63, _64, _65, _66, _67, _68, _69, N, ...) N
#define VISIT_STRUCT_PP_NARG(...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_PP_ARG_N(__VA_ARGS__, \
69, 68, 67, 66, 65, 64, 63, 62, 61, 60, \
59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
/* need extra level to force extra eval */
#define VISIT_STRUCT_CONCAT_(a,b) a ## b
#define VISIT_STRUCT_CONCAT(a,b) VISIT_STRUCT_CONCAT_(a,b)
#define VISIT_STRUCT_APPLYF0(f)
#define VISIT_STRUCT_APPLYF1(f,_1) f(_1)
#define VISIT_STRUCT_APPLYF2(f,_1,_2) f(_1) f(_2)
#define VISIT_STRUCT_APPLYF3(f,_1,_2,_3) f(_1) f(_2) f(_3)
#define VISIT_STRUCT_APPLYF4(f,_1,_2,_3,_4) f(_1) f(_2) f(_3) f(_4)
#define VISIT_STRUCT_APPLYF5(f,_1,_2,_3,_4,_5) f(_1) f(_2) f(_3) f(_4) f(_5)
#define VISIT_STRUCT_APPLYF6(f,_1,_2,_3,_4,_5,_6) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6)
#define VISIT_STRUCT_APPLYF7(f,_1,_2,_3,_4,_5,_6,_7) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7)
#define VISIT_STRUCT_APPLYF8(f,_1,_2,_3,_4,_5,_6,_7,_8) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8)
#define VISIT_STRUCT_APPLYF9(f,_1,_2,_3,_4,_5,_6,_7,_8,_9) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9)
#define VISIT_STRUCT_APPLYF10(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10)
#define VISIT_STRUCT_APPLYF11(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11)
#define VISIT_STRUCT_APPLYF12(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12)
#define VISIT_STRUCT_APPLYF13(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13)
#define VISIT_STRUCT_APPLYF14(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14)
#define VISIT_STRUCT_APPLYF15(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15)
#define VISIT_STRUCT_APPLYF16(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16)
#define VISIT_STRUCT_APPLYF17(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17)
#define VISIT_STRUCT_APPLYF18(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18)
#define VISIT_STRUCT_APPLYF19(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19)
#define VISIT_STRUCT_APPLYF20(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20)
#define VISIT_STRUCT_APPLYF21(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21)
#define VISIT_STRUCT_APPLYF22(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22)
#define VISIT_STRUCT_APPLYF23(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23)
#define VISIT_STRUCT_APPLYF24(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24)
#define VISIT_STRUCT_APPLYF25(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25)
#define VISIT_STRUCT_APPLYF26(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26)
#define VISIT_STRUCT_APPLYF27(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27)
#define VISIT_STRUCT_APPLYF28(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28)
#define VISIT_STRUCT_APPLYF29(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29)
#define VISIT_STRUCT_APPLYF30(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30)
#define VISIT_STRUCT_APPLYF31(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31)
#define VISIT_STRUCT_APPLYF32(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32)
#define VISIT_STRUCT_APPLYF33(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33)
#define VISIT_STRUCT_APPLYF34(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34)
#define VISIT_STRUCT_APPLYF35(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35)
#define VISIT_STRUCT_APPLYF36(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36)
#define VISIT_STRUCT_APPLYF37(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37)
#define VISIT_STRUCT_APPLYF38(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38)
#define VISIT_STRUCT_APPLYF39(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39)
#define VISIT_STRUCT_APPLYF40(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40)
#define VISIT_STRUCT_APPLYF41(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41)
#define VISIT_STRUCT_APPLYF42(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42)
#define VISIT_STRUCT_APPLYF43(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43)
#define VISIT_STRUCT_APPLYF44(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44)
#define VISIT_STRUCT_APPLYF45(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45)
#define VISIT_STRUCT_APPLYF46(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46)
#define VISIT_STRUCT_APPLYF47(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47)
#define VISIT_STRUCT_APPLYF48(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48)
#define VISIT_STRUCT_APPLYF49(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49)
#define VISIT_STRUCT_APPLYF50(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50)
#define VISIT_STRUCT_APPLYF51(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51)
#define VISIT_STRUCT_APPLYF52(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52)
#define VISIT_STRUCT_APPLYF53(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53)
#define VISIT_STRUCT_APPLYF54(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54)
#define VISIT_STRUCT_APPLYF55(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55)
#define VISIT_STRUCT_APPLYF56(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56)
#define VISIT_STRUCT_APPLYF57(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57)
#define VISIT_STRUCT_APPLYF58(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58)
#define VISIT_STRUCT_APPLYF59(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59)
#define VISIT_STRUCT_APPLYF60(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60)
#define VISIT_STRUCT_APPLYF61(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61)
#define VISIT_STRUCT_APPLYF62(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62)
#define VISIT_STRUCT_APPLYF63(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63)
#define VISIT_STRUCT_APPLYF64(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64)
#define VISIT_STRUCT_APPLYF65(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65)
#define VISIT_STRUCT_APPLYF66(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66)
#define VISIT_STRUCT_APPLYF67(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67)
#define VISIT_STRUCT_APPLYF68(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68)
#define VISIT_STRUCT_APPLYF69(f,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68,_69) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16) f(_17) f(_18) f(_19) f(_20) f(_21) f(_22) f(_23) f(_24) f(_25) f(_26) f(_27) f(_28) f(_29) f(_30) f(_31) f(_32) f(_33) f(_34) f(_35) f(_36) f(_37) f(_38) f(_39) f(_40) f(_41) f(_42) f(_43) f(_44) f(_45) f(_46) f(_47) f(_48) f(_49) f(_50) f(_51) f(_52) f(_53) f(_54) f(_55) f(_56) f(_57) f(_58) f(_59) f(_60) f(_61) f(_62) f(_63) f(_64) f(_65) f(_66) f(_67) f(_68) f(_69)
#define VISIT_STRUCT_APPLY_F_(M, ...) VISIT_STRUCT_EXPAND(M(__VA_ARGS__))
#define VISIT_STRUCT_PP_MAP(f, ...) VISIT_STRUCT_EXPAND(VISIT_STRUCT_APPLY_F_(VISIT_STRUCT_CONCAT(VISIT_STRUCT_APPLYF, VISIT_STRUCT_PP_NARG(__VA_ARGS__)), f, __VA_ARGS__))
/*** End generated code ***/
/***
* These macros are used with VISIT_STRUCT_PP_MAP
*/
#define VISIT_STRUCT_FIELD_COUNT(MEMBER_NAME) \
+ 1
#define VISIT_STRUCT_MEMBER_HELPER(MEMBER_NAME) \
std::forward<V>(visitor)(#MEMBER_NAME, std::forward<S>(struct_instance).MEMBER_NAME);
#define VISIT_STRUCT_MEMBER_HELPER_PTR(MEMBER_NAME) \
std::forward<V>(visitor)(#MEMBER_NAME, &this_type::MEMBER_NAME);
#define VISIT_STRUCT_MEMBER_HELPER_TYPE(MEMBER_NAME) \
std::forward<V>(visitor)(#MEMBER_NAME, visit_struct::type_c<decltype(this_type::MEMBER_NAME)>{});
#define VISIT_STRUCT_MEMBER_HELPER_ACC(MEMBER_NAME) \
std::forward<V>(visitor)(#MEMBER_NAME, visit_struct::accessor<decltype(&this_type::MEMBER_NAME), &this_type::MEMBER_NAME>{});
#define VISIT_STRUCT_MEMBER_HELPER_PAIR(MEMBER_NAME) \
std::forward<V>(visitor)(#MEMBER_NAME, std::forward<S1>(s1).MEMBER_NAME, std::forward<S2>(s2).MEMBER_NAME);
#define VISIT_STRUCT_MAKE_GETTERS(MEMBER_NAME) \
template <typename S> \
static VISIT_STRUCT_CONSTEXPR auto \
get_value(std::integral_constant<int, fields_enum::MEMBER_NAME>, S && s) -> \
decltype((std::forward<S>(s).MEMBER_NAME)) { \
return std::forward<S>(s).MEMBER_NAME; \
} \
\
static VISIT_STRUCT_CONSTEXPR auto \
get_name(std::integral_constant<int, fields_enum::MEMBER_NAME>) -> \
decltype(#MEMBER_NAME) { \
return #MEMBER_NAME; \
} \
\
static VISIT_STRUCT_CONSTEXPR auto \
get_pointer(std::integral_constant<int, fields_enum::MEMBER_NAME>) -> \
decltype(&this_type::MEMBER_NAME) { \
return &this_type::MEMBER_NAME; \
} \
\
static VISIT_STRUCT_CONSTEXPR auto \
get_accessor(std::integral_constant<int, fields_enum::MEMBER_NAME>) -> \
visit_struct::accessor<decltype(&this_type::MEMBER_NAME), &this_type::MEMBER_NAME > { \
return {}; \
} \
\
static auto \
type_at(std::integral_constant<int, fields_enum::MEMBER_NAME>) -> \
visit_struct::type_c<decltype(this_type::MEMBER_NAME)>;
// This macro specializes the trait, provides "apply" method which does the work.
// Below, template parameter S should always be the same as STRUCT_NAME modulo const and reference.
// The interface defined above ensures that STRUCT_NAME is clean_t<S> basically.
//
// Note: The code to make the indexed getters work is more convoluted than I'd like.
// PP_MAP doesn't give you the index of each member. And rather than hack it so that it will
// do that, what we do instead is:
// 1: Declare an enum `field_enum` in the scope of visitable, which maps names to indices.
// This gives an easy way for the macro to get the index from the name token.
// 2: Intuitively we'd like to use template partial specialization to make indices map to
// values, and have a new specialization for each member. But, specializations can only
// be made at namespace scope. So to keep things tidy and contained within this trait,
// we use tag dispatch with std::integral_constant<int> instead.
#define VISITABLE_STRUCT(STRUCT_NAME, ...) \
namespace visit_struct { \
namespace traits { \
\
template <> \
struct visitable<STRUCT_NAME, void> { \
\
using this_type = STRUCT_NAME; \
\
static VISIT_STRUCT_CONSTEXPR auto get_name() \
-> decltype(#STRUCT_NAME) { \
return #STRUCT_NAME; \
} \
\
static VISIT_STRUCT_CONSTEXPR const std::size_t field_count = 0 \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_FIELD_COUNT, __VA_ARGS__); \
\
template <typename V, typename S> \
VISIT_STRUCT_CXX14_CONSTEXPR static void apply(V && visitor, S && struct_instance) \
{ \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MEMBER_HELPER, __VA_ARGS__) \
} \
\
template <typename V, typename S1, typename S2> \
VISIT_STRUCT_CXX14_CONSTEXPR static void apply(V && visitor, S1 && s1, S2 && s2) \
{ \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MEMBER_HELPER_PAIR, __VA_ARGS__) \
} \
\
template <typename V> \
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_pointers(V && visitor) \
{ \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MEMBER_HELPER_PTR, __VA_ARGS__) \
} \
\
template <typename V> \
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_types(V && visitor) \
{ \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MEMBER_HELPER_TYPE, __VA_ARGS__) \
} \
\
template <typename V> \
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_accessors(V && visitor) \
{ \
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MEMBER_HELPER_ACC, __VA_ARGS__) \
} \
\
struct fields_enum { \
enum index { __VA_ARGS__ }; \
}; \
\
VISIT_STRUCT_PP_MAP(VISIT_STRUCT_MAKE_GETTERS, __VA_ARGS__) \
\
static VISIT_STRUCT_CONSTEXPR const bool value = true; \
}; \
\
} \
} \
static_assert(true, "")
} // end namespace visit_struct
#endif // VISIT_STRUCT_HPP_INCLUDED
// (C) Copyright 2015 - 2018 Christopher Beck
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef VISIT_STRUCT_INTRUSIVE_HPP_INCLUDED
#define VISIT_STRUCT_INTRUSIVE_HPP_INCLUDED
/***
* A collection of templates and macros supporting a second form of VISIT_STRUCT
* mechanism.
*
* In this version, the visitable members are declared *within* the body of the
* struct, at the same time that they are actually declared.
*
* This version uses templates for iteration rather than macros, so it's really
* fairly different. It is more DRY and less likely to produce gross error
* messages than the other, at the cost of being invasive to your structure
* definition.
*
* This version adds some typedefs to your class, and it invisibly adds some
* declarations of obscure member functions to your class. These declarations
* do not have corresponding definitions and generate no object code, they are
* merely a device for metaprogramming, exploiting overload resolution rules to
* create "state". In normal code, you won't be able to detect any of this.
*
* This sounds a lot more evil than it really is -- it is morally equivalent to
* `std::declval`, I would say, which is also specified to be a declaration with
* no definition, which you simply aren't permitted to odr-use.
*/
// #include <visit_struct/visit_struct.hpp>
namespace visit_struct {
namespace detail {
/***
* Poor man's mpl vector
*/
template <class... Ts>
struct TypeList {
static VISIT_STRUCT_CONSTEXPR const unsigned int size = sizeof...(Ts);
};
// Append metafunction
template <class List, class T>
struct Append;
template <class... Ts, class T>
struct Append<TypeList<Ts...>, T> {
typedef TypeList<Ts..., T> type;
};
template<class L, class T>
using Append_t = typename Append<L, T>::type;
// Cdr metafunction (cdr is a lisp function which returns the tail of a list)
template <class List>
struct Cdr;
template <typename T, typename... Ts>
struct Cdr<TypeList<T, Ts...>> {
typedef TypeList<Ts...> type;
};
template <class List>
using Cdr_t = typename Cdr<List>::type;
// Find metafunction (get the idx'th element)
template <class List, unsigned idx>
struct Find : Find<Cdr_t<List>, idx - 1> {};
template <typename T, typename... Ts>
struct Find<TypeList<T, Ts...>, 0> {
typedef T type;
};
template <class List, unsigned idx>
using Find_t = typename Find<List, idx>::type;
// Alias used when capturing references to string literals
template <int N>
using char_array = const char [N];
/***
* The "rank" template is a trick which can be used for
* certain metaprogramming techniques. It creates
* an inheritance hierarchy of trivial classes.
*/
template <int N>
struct Rank : Rank<N - 1> {};
template <>
struct Rank<0> {};
static VISIT_STRUCT_CONSTEXPR const int max_visitable_members_intrusive = 100;
/***
* To create a "compile-time" TypeList whose members are accumulated one-by-one,
* the basic idea is to define a function, which takes a `Rank` object, and
* whose return type is the type representing the current value of the list.
*
* That function is not a template function -- it is defined as taking a
* particular rank object. Initially, it is defined only for `Rank<0>`.
*
* To add an element to the list, we define an overload of the function, which
* takes the next higher `Rank` as it's argument. It's return value is,
* the new value of the list, formed by using `Append_t` with the old value.
*
* To obtain the current value of the list, we use decltype with the name of the
* function, and `Rank<100>`, or some suitably large integer. The C++ standard
* specifies that overload resolution is in this case unambiguous and must
* select the overload for the "most-derived" type which matches.
*
* The upshot is that `decltype(my_function(Rank<100>{}))` is a single well-formed
* expression, which, because of C++ overload resolution rules, can be a
* "mutable" value from the point of view of metaprogramming.
*
*
* Attribution:
* I first learned this trick from a stackoverflow post by Roman Perepelitsa:
* http://stackoverflow.com/questions/4790721/c-type-registration-at-compile-time-trick
*
* He attributes it to a talk from Matt Calabrese at BoostCon 2011.
*
*
* The expression is inherently dangerous if you are using it inside the body
* of a struct -- obviously, it has different values at different points of the
* structure definition. The "END_VISITABLES" macro is important in that this
* finalizes the list, typedeffing `decltype(my_function(Rank<100>{}))` to some
* fixed name in your struct at a specific point in the definition. That
* typedef can only ultimately have one meaning, no matter where else the name
* may be used (even implicitly) in your structure definition. That typedef is
* what the trait defined in this header ultimately hooks into to find the
* visitable members.
*/
// A tag inserted into a structure to mark it as visitable
struct intrusive_tag{};
/***
* Helper structures which perform pack expansion in order to visit a structure.
*/
// In MSVC 2015, sometimes a pointer to member cannot be constexpr, for instance
// I had trouble with code like this:
//
// struct S {
// int a;
// static constexpr auto a_ptr = &S::a;
// };
//
// This works fine in gcc and clang.
// MSVC is okay with it if instead it is a template parameter it seems, so we
// use `member_ptr_helper` below as a workaround, a bit like so:
//
// struct S {
// int a;
// using a_helper = member_ptr_helper<S, int, &S::a>;
// };
template <typename S, typename T, T S::*member_ptr>
struct member_ptr_helper {
static VISIT_STRUCT_CONSTEXPR T S::* get_ptr() { return member_ptr; }
using value_type = T;
using accessor_t = visit_struct::accessor<T S::*, member_ptr>;
};
// M should be derived from a member_ptr_helper
template <typename M>
struct member_helper {
template <typename V, typename S>
VISIT_STRUCT_CXX14_CONSTEXPR static void apply_visitor(V && visitor, S && structure_instance) {
std::forward<V>(visitor)(M::member_name(), std::forward<S>(structure_instance).*M::get_ptr());
}
template <typename V, typename S1, typename S2>
VISIT_STRUCT_CXX14_CONSTEXPR static void apply_visitor(V && visitor, S1 && s1, S2 && s2) {
std::forward<V>(visitor)(M::member_name(),
std::forward<S1>(s1).*M::get_ptr(),
std::forward<S2>(s2).*M::get_ptr());
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_pointers(V && visitor) {
std::forward<V>(visitor)(M::member_name(), M::get_ptr());
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_accessors(V && visitor) {
std::forward<V>(visitor)(M::member_name(), typename M::accessor_t());
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_types(V && visitor) {
std::forward<V>(visitor)(M::member_name(), visit_struct::type_c<typename M::value_type>{});
}
};
template <typename Mlist>
struct structure_helper;
template <typename... Ms>
struct structure_helper<TypeList<Ms...>> {
template <typename V, typename S>
VISIT_STRUCT_CXX14_CONSTEXPR static void apply_visitor(V && visitor, S && structure_instance) {
// Use parameter pack expansion to force evaluation of the member helper for each member in the list.
// Inside parens, a comma operator is being used to discard the void value and produce an integer, while
// not being an unevaluated context. The order of evaluation here is enforced by the compiler.
// Extra zero at the end is to avoid UB for having a zero-size array.
int dummy[] = {(member_helper<Ms>::apply_visitor(std::forward<V>(visitor), std::forward<S>(structure_instance)), 0)..., 0};
// Suppress unused warnings, even in case of empty parameter pack
static_cast<void>(dummy);
static_cast<void>(visitor);
static_cast<void>(structure_instance);
}
template <typename V, typename S1, typename S2>
VISIT_STRUCT_CXX14_CONSTEXPR static void apply_visitor(V && visitor, S1 && s1, S2 && s2) {
int dummy[] = {(member_helper<Ms>::apply_visitor(std::forward<V>(visitor), std::forward<S1>(s1), std::forward<S2>(s2)), 0)..., 0};
static_cast<void>(dummy);
static_cast<void>(visitor);
static_cast<void>(s1);
static_cast<void>(s2);
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_pointers(V && visitor) {
int dummy[] = {(member_helper<Ms>::visit_pointers(std::forward<V>(visitor)), 0)..., 0};
static_cast<void>(dummy);
static_cast<void>(visitor);
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_accessors(V && visitor) {
int dummy[] = {(member_helper<Ms>::visit_accessors(std::forward<V>(visitor)), 0)..., 0};
static_cast<void>(dummy);
static_cast<void>(visitor);
}
template <typename V>
VISIT_STRUCT_CXX14_CONSTEXPR static void visit_types(V && visitor) {
int dummy[] = {(member_helper<Ms>::visit_types(std::forward<V>(visitor)), 0)..., 0};
static_cast<void>(dummy);
static_cast<void>(visitor);
}
};
} // end namespace detail
/***
* Implement trait
*/
namespace traits {
template <typename T>
struct visitable <T,
typename std::enable_if<
std::is_same<typename T::Visit_Struct_Visitable_Structure_Tag__,
::visit_struct::detail::intrusive_tag
>::value
>::type
>
{
static VISIT_STRUCT_CONSTEXPR const std::size_t field_count = T::Visit_Struct_Registered_Members_List__::size;
// Apply to an instance
// S should be the same type as T modulo const and reference
template <typename V, typename S>
static VISIT_STRUCT_CXX14_CONSTEXPR void apply(V && v, S && s) {
detail::structure_helper<typename T::Visit_Struct_Registered_Members_List__>::apply_visitor(std::forward<V>(v), std::forward<S>(s));
}
// Apply with two instances
template <typename V, typename S1, typename S2>
static VISIT_STRUCT_CXX14_CONSTEXPR void apply(V && v, S1 && s1, S2 && s2) {
detail::structure_helper<typename T::Visit_Struct_Registered_Members_List__>::apply_visitor(std::forward<V>(v), std::forward<S1>(s1), std::forward<S2>(s2));
}
// Apply with no instance
template <typename V>
static VISIT_STRUCT_CXX14_CONSTEXPR void visit_pointers(V && v) {
detail::structure_helper<typename T::Visit_Struct_Registered_Members_List__>::visit_pointers(std::forward<V>(v));
}
template <typename V>
static VISIT_STRUCT_CXX14_CONSTEXPR void visit_types(V && v) {
detail::structure_helper<typename T::Visit_Struct_Registered_Members_List__>::visit_types(std::forward<V>(v));
}
template <typename V>
static VISIT_STRUCT_CXX14_CONSTEXPR void visit_accessors(V && v) {
detail::structure_helper<typename T::Visit_Struct_Registered_Members_List__>::visit_accessors(std::forward<V>(v));
}
// Get pointer
template <int idx>
static VISIT_STRUCT_CONSTEXPR auto get_pointer(std::integral_constant<int, idx>)
-> decltype(detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::get_ptr())
{
return detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::get_ptr();
}
// Get accessor
template <int idx>
static VISIT_STRUCT_CONSTEXPR auto get_accessor(std::integral_constant<int, idx>)
-> typename detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::accessor_t
{
return {};
}
// Get value
template <int idx, typename S>
static VISIT_STRUCT_CONSTEXPR auto get_value(std::integral_constant<int, idx> tag, S && s)
-> decltype(std::forward<S>(s).*get_pointer(tag))
{
return std::forward<S>(s).*get_pointer(tag);
}
// Get name
template <int idx>
static VISIT_STRUCT_CONSTEXPR auto get_name(std::integral_constant<int, idx>)
-> decltype(detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::member_name())
{
return detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::member_name();
}
// Get type
template <int idx>
static auto type_at(std::integral_constant<int, idx>)
-> visit_struct::type_c<typename detail::Find_t<typename T::Visit_Struct_Registered_Members_List__, idx>::value_type>;
// Get name of structure
static VISIT_STRUCT_CONSTEXPR decltype(T::Visit_Struct_Get_Name__()) get_name() {
return T::Visit_Struct_Get_Name__();
}
static VISIT_STRUCT_CONSTEXPR const bool value = true;
};
} // end namespace trait
} // end namespace visit_struct
// Macros to be used within a structure definition
#define VISIT_STRUCT_GET_REGISTERED_MEMBERS decltype(Visit_Struct_Get_Visitables__(::visit_struct::detail::Rank<visit_struct::detail::max_visitable_members_intrusive>{}))
#define VISIT_STRUCT_MAKE_MEMBER_NAME(NAME) Visit_Struct_Member_Record__##NAME
#define BEGIN_VISITABLES(NAME) \
typedef NAME VISIT_STRUCT_CURRENT_TYPE; \
static VISIT_STRUCT_CONSTEXPR decltype(#NAME) Visit_Struct_Get_Name__() { \
return #NAME; \
} \
::visit_struct::detail::TypeList<> static inline Visit_Struct_Get_Visitables__(::visit_struct::detail::Rank<0>); \
static_assert(true, "")
#define VISITABLE(TYPE, NAME) \
TYPE NAME; \
struct VISIT_STRUCT_MAKE_MEMBER_NAME(NAME) : \
visit_struct::detail::member_ptr_helper<VISIT_STRUCT_CURRENT_TYPE, \
TYPE, \
&VISIT_STRUCT_CURRENT_TYPE::NAME> \
{ \
static VISIT_STRUCT_CONSTEXPR const ::visit_struct::detail::char_array<sizeof(#NAME)> & member_name() { \
return #NAME; \
} \
}; \
static inline ::visit_struct::detail::Append_t<VISIT_STRUCT_GET_REGISTERED_MEMBERS, \
VISIT_STRUCT_MAKE_MEMBER_NAME(NAME)> \
Visit_Struct_Get_Visitables__(::visit_struct::detail::Rank<VISIT_STRUCT_GET_REGISTERED_MEMBERS::size + 1>); \
static_assert(true, "")
#define VISITABLE_INIT(TYPE, NAME, VALUE) \
TYPE NAME = VALUE; \
struct VISIT_STRUCT_MAKE_MEMBER_NAME(NAME) : \
visit_struct::detail::member_ptr_helper<VISIT_STRUCT_CURRENT_TYPE, \
TYPE, \
&VISIT_STRUCT_CURRENT_TYPE::NAME> \
{ \
static VISIT_STRUCT_CONSTEXPR const ::visit_struct::detail::char_array<sizeof(#NAME)> & member_name() { \
return #NAME; \
} \
}; \
static inline ::visit_struct::detail::Append_t<VISIT_STRUCT_GET_REGISTERED_MEMBERS, \
VISIT_STRUCT_MAKE_MEMBER_NAME(NAME)> \
Visit_Struct_Get_Visitables__(::visit_struct::detail::Rank<VISIT_STRUCT_GET_REGISTERED_MEMBERS::size + 1>); \
static_assert(true, "")
#define VISITABLE_DIRECT_INIT(TYPE, NAME, ...) \
TYPE NAME __VA_ARGS__; \
struct VISIT_STRUCT_MAKE_MEMBER_NAME(NAME) : \
visit_struct::detail::member_ptr_helper<VISIT_STRUCT_CURRENT_TYPE, \
TYPE, \
&VISIT_STRUCT_CURRENT_TYPE::NAME> \
{ \
static VISIT_STRUCT_CONSTEXPR const ::visit_struct::detail::char_array<sizeof(#NAME)>& member_name() \
{ \
return #NAME; \
} \
}; \
static inline ::visit_struct::detail::Append_t<VISIT_STRUCT_GET_REGISTERED_MEMBERS, \
VISIT_STRUCT_MAKE_MEMBER_NAME(NAME)> \
Visit_Struct_Get_Visitables__(::visit_struct::detail::Rank<VISIT_STRUCT_GET_REGISTERED_MEMBERS::size + 1>); \
static_assert(true, "")
#define END_VISITABLES \
typedef VISIT_STRUCT_GET_REGISTERED_MEMBERS Visit_Struct_Registered_Members_List__; \
typedef ::visit_struct::detail::intrusive_tag Visit_Struct_Visitable_Structure_Tag__; \
static_assert(true, "")
#endif // VISIT_STRUCT_INTRUSIVE_HPP_INCLUDED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment