// Copyright satoren // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #pragma once #include #include "kaguya/config.hpp" #include "kaguya/utility.hpp" #include "kaguya/preprocess.hpp" namespace kaguya { namespace fntuple { #if KAGUYA_USE_CPP11 && !defined(KAGUYA_FUNCTION_MAX_OVERLOADS) // In Clang with libstdc++. // std::tuple elements is limited to 16 for template depth limit using std::tuple; using std::get; using std::tuple_element; using std::tuple_size; #else using util::null_type; // boost::tuple is max #define KAGUYA_PP_STRUCT_TDEF_REP(N) KAGUYA_PP_CAT(typename A, N) = null_type #define KAGUYA_PP_STRUCT_TEMPLATE_DEF_REPEAT(N) \ KAGUYA_PP_REPEAT_ARG(N, KAGUYA_PP_STRUCT_TDEF_REP) template struct tuple {}; #undef KAGUYA_PP_STRUCT_TDEF_REP #undef KAGUYA_PP_STRUCT_TEMPLATE_DEF_REPEAT #define KAGUYA_FUNCTION_TUPLE_ELEMENT(N) \ KAGUYA_PP_CAT(A, N) KAGUYA_PP_CAT(elem, N); #define KAGUYA_FUNCTION_TUPLE_ELEMENT_INIT(N) \ KAGUYA_PP_CAT(elem, N)(KAGUYA_PP_CAT(a, N)) #define KAGUYA_FUNCTION_TUPLE_IMPL_DEF(N) \ template \ struct tuple { \ KAGUYA_PP_REPEAT(N, KAGUYA_FUNCTION_TUPLE_ELEMENT) \ tuple(KAGUYA_PP_ARG_DEF_REPEAT(N)) \ : KAGUYA_PP_REPEAT_ARG(N, KAGUYA_FUNCTION_TUPLE_ELEMENT_INIT) {} \ }; KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_OVERLOADS, KAGUYA_FUNCTION_TUPLE_IMPL_DEF) template struct tuple_size; #define KAGUYA_TUPLE_SIZE_DEF(N) \ template \ struct tuple_size > { \ static const size_t value = N; \ }; KAGUYA_TUPLE_SIZE_DEF(0) KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_OVERLOADS, KAGUYA_TUPLE_SIZE_DEF) #undef KAGUYA_TUPLE_SIZE_DEF template struct tuple_element {}; #define KAGUYA_TUPLE_ELEMENT_DEF(N) \ template \ struct tuple_element< \ remain, tuple, true> { \ typedef arg type; \ }; \ template \ struct tuple_element< \ remain, tuple, false> \ : tuple_element > { \ }; KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_OVERLOADS, KAGUYA_TUPLE_ELEMENT_DEF) #undef KAGUYA_TUPLE_SIZE_DEF template struct tuple_get_helper; #define KAGUYA_TUPLE_GET_DEF(N) \ template struct tuple_get_helper { \ static typename tuple_element::type &get(T &t) { \ return t.KAGUYA_PP_CAT(elem, N); \ } \ static const typename tuple_element::type &cget(const T &t) { \ return t.KAGUYA_PP_CAT(elem, N); \ } \ }; KAGUYA_PP_REPEAT_DEF(KAGUYA_FUNCTION_MAX_OVERLOADS, KAGUYA_TUPLE_GET_DEF) template typename tuple_element::type &get(T &t) { return tuple_get_helper::get(t); } template const typename tuple_element::type &get(const T &t) { return tuple_get_helper::cget(t); } #endif } }