/************************************************************************************ * * * Copyright (c) 2014 - 2018 Axel Menzel * * * * This file is part of RTTR (Run Time Type Reflection) * * License: MIT License * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * * SOFTWARE. * * * *************************************************************************************/ #ifndef RTTR_PARAMETER_INFOS_H_ #define RTTR_PARAMETER_INFOS_H_ #include "rttr/detail/base/core_prerequisites.h" #include "rttr/detail/parameter_info/parameter_info_wrapper.h" #include "rttr/detail/default_arguments/default_arguments.h" #include "rttr/parameter_info.h" namespace rttr { namespace detail { ///////////////////////////////////////////////////////////////////////////////////////// template struct parameter_infos { parameter_infos() {} parameter_infos(T&&... args) : m_param_infos(std::forward(args)...) {} std::tuple m_param_infos; RTTR_STATIC_CONSTEXPR std::size_t count = sizeof...(T); }; template<> struct parameter_infos<> { parameter_infos() {} std::tuple<> m_param_infos; RTTR_STATIC_CONSTEXPR std::size_t count = 0; }; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template using has_param_names = std::integral_constant>::value>; template using count_param_names = count_if... >; template struct param_names_count_impl; template struct param_names_count_impl, enable_if_t::value>> { RTTR_STATIC_CONSTEXPR std::size_t count = find_if_t::count; }; template struct param_names_count_impl, enable_if_t::value>> { RTTR_STATIC_CONSTEXPR std::size_t count = 0; }; template using param_names_count = std::integral_constant>::count>; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE parameter_info create_param_info(const T& data) { return parameter_info(&data); } template static RTTR_INLINE std::array create_paramter_info_array_impl(index_sequence, const parameter_infos& param_infos) { return { {create_param_info(std::get(param_infos.m_param_infos))...} }; }; // MSVC 2015 cannot handle sizeof...(), // I retrieve a fatal error C1001: An internal error has occurred in the compiler. // (compiler file 'msc1.cpp', line 1421) // MSVC 2013 can handle it... template static RTTR_INLINE std::array create_paramter_info_array(const parameter_infos& param_infos) { return create_paramter_info_array_impl(make_index_sequence(), param_infos); }; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template struct param_info_creater_func_impl; template struct param_info_creater_func_impl> { using type = parameter_infos< parameter_info_wrapper, Arg_Count, Has_Name, type_list_element_t >...>; }; ///////////////////////////////////////////////////////////////////////////////////////// template struct param_info_creater_ctor_impl; template struct param_info_creater_ctor_impl> { using type = parameter_infos< parameter_info_wrapper, Arg_Count, Has_Name, type_list_element_t >...>; }; ///////////////////////////////////////////////////////////////////////////////////////// template struct param_info_creater; // for functions template struct param_info_creater, Acc_Type, Has_Name, type_list, enable_if_t< std::is_same::value >> { using new_default_list = push_front_n_t, function_traits::arg_count - sizeof...(Def_Args)>; using idx_seq = make_index_sequence< function_traits::arg_count>; using type = typename param_info_creater_func_impl::type; }; // ctor with one argument template struct param_info_creater, constructor_type, Has_Name, type_list, enable_if_t< is_one_argument::value >> { static_assert(sizeof...(Def_Args) < 2, "Invalid 'Def_Args' size."); using new_default_list = push_front_n_t, 1 - sizeof...(Def_Args)>; using idx_seq = make_index_sequence<1>; using type = typename param_info_creater_ctor_impl, Has_Name, new_default_list, idx_seq>::type; }; // ctor with zero or more then one argument template struct param_info_creater, constructor_type, Has_Name, type_list, enable_if_t< !is_one_argument::value >> { static_assert(sizeof...(Ctor_Args) >= sizeof...(Def_Args), "Invalid 'Def_Args' size."); using new_default_list = push_front_n_t, sizeof...(Ctor_Args) - sizeof...(Def_Args)>; using idx_seq = make_index_sequence< sizeof...(Ctor_Args) >; using type = typename param_info_creater_ctor_impl, Has_Name, new_default_list, idx_seq>::type; }; template using param_info_creater_t = typename param_info_creater::type; ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE param_info_creater_t create_param_infos_and_store_names(index_sequence, Param_Names& names) { return param_info_creater_t{string_view(std::get(names.m_param_names))...}; } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template, Acc_Args, Acc_Type>::default_types_func>> static RTTR_INLINE enable_if_t< !has_param_names::value && has_default_types, Acc_Type>::value, param_info_creater_t> create_param_infos(TArgs&&... args) { return param_info_creater_t(); } ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE enable_if_t< !has_param_names::value && !has_default_types, Acc_Type>::value, param_info_creater_t >> create_param_infos(TArgs&&... args) { return param_info_creater_t >(); } ///////////////////////////////////////////////////////////////////////////////////////// template, Acc_Args, Acc_Type>::default_types_func>> static RTTR_INLINE enable_if_t< has_param_names::value && has_default_types, Acc_Type>::value, param_info_creater_t> create_param_infos(TArgs&&... args) { using Param_Type = find_if_t; auto result = forward_to_array(std::forward(args)...); return create_param_infos_and_store_names(make_index_sequence(), result[0]); } ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE enable_if_t< has_param_names::value && !has_default_types, Acc_Type>::value, param_info_creater_t >> create_param_infos(TArgs&&... args) { using Param_Type = find_if_t; auto result = forward_to_array(std::forward(args)...); return create_param_infos_and_store_names>(make_index_sequence(), result[0]); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE void store_default_value(Param_Arg& param_info, const Default_Args& def_arg) { param_info.set_default_value(&def_arg); } ///////////////////////////////////////////////////////////////////////////////////////// template struct store_default_args_helper; template struct store_default_args_helper, index_sequence> { template static RTTR_INLINE void perform(parameter_infos& param_infos, const default_args& def_args) { store_default_value(std::get(param_infos.m_param_infos), std::get(def_args.m_args)); store_default_args_helper, index_sequence>::perform(param_infos, def_args); } }; template<> struct store_default_args_helper, index_sequence<>> { template static RTTR_INLINE void perform(parameter_infos& param_infos, const default_args& def_args) { } }; ///////////////////////////////////////////////////////////////////////////////////////// template static RTTR_INLINE void store_default_args_in_param_infos(parameter_infos& param_infos, const default_args& def_args) { static_assert((sizeof...(Default_Args) <= sizeof...(Param_Args)), "Invalid size of default arguments!"); using param_idx_seq = typename erase_sequence_till, sizeof...(Param_Args) - sizeof...(Default_Args)>::type; store_default_args_helper, param_idx_seq>::perform(param_infos, def_args); } ///////////////////////////////////////////////////////////////////////////////////////// } // end namespace detail } // end namespace rttr #endif // RTTR_PARAMETER_INFOS_H_