Created
May 26, 2018 15:35
-
-
Save notfoundry/25d0a55067e111c5fb15442839639d28 to your computer and use it in GitHub Desktop.
Keep some default template parameters of a type while replacing others
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 <boost/mp11/list.hpp> | |
| #include <boost/mp11/utility.hpp> | |
| #include <boost/mp11/algorithm.hpp> | |
| #include <type_traits> | |
| #include <cstddef> | |
| struct _ {}; | |
| namespace detail { | |
| using namespace boost::mp11; | |
| template <typename ArgsList> | |
| struct find_index_of_first_default { | |
| using type = mp_find<ArgsList, _>; | |
| }; | |
| template<template <typename...> class Template, typename ArgsListBeforeDefaults> | |
| struct get_default_arguments { | |
| private: | |
| using instantiated_type_with_all_defaults = mp_apply<Template, ArgsListBeforeDefaults>; | |
| using all_types_list = mp_rename<instantiated_type_with_all_defaults, mp_list>; | |
| using default_arguments = mp_drop<all_types_list, mp_size<ArgsListBeforeDefaults>>; | |
| public: | |
| using type = default_arguments; | |
| }; | |
| template < | |
| typename ArgsListReplacingDefaults, typename DefaultArgsList, | |
| typename FinalArgTypeAccumulator = mp_list<>, | |
| std::size_t Remaining = mp_size<ArgsListReplacingDefaults>::value | |
| > | |
| struct replace_placeholders_with_default_arguments_impl { | |
| private: | |
| using current_replacement = mp_front<ArgsListReplacingDefaults>; | |
| using current_default = mp_front<DefaultArgsList>; | |
| using final_arg_type = mp_if<std::is_same<current_replacement, _>, current_default, current_replacement>; | |
| using next_replacement_list_step = mp_pop_front<ArgsListReplacingDefaults>; | |
| using next_default_args_list_step = mp_pop_front<DefaultArgsList>; | |
| using next_accumulator_step = mp_push_back<FinalArgTypeAccumulator, final_arg_type>; | |
| public: | |
| using type = typename replace_placeholders_with_default_arguments_impl<next_replacement_list_step, next_default_args_list_step, next_accumulator_step>::type; | |
| }; | |
| template <typename ArgsListReplacingDefaults, typename DefaultArgsList, typename FinalArgTypeAccumulator> | |
| struct replace_placeholders_with_default_arguments_impl<ArgsListReplacingDefaults, DefaultArgsList, FinalArgTypeAccumulator, 0> { | |
| using type = FinalArgTypeAccumulator; | |
| }; | |
| template <typename ArgsListReplacingDefaults, typename DefaultArgsList> | |
| struct replace_placeholders_with_default_arguments { | |
| using type = typename replace_placeholders_with_default_arguments_impl<ArgsListReplacingDefaults, DefaultArgsList>::type; | |
| }; | |
| template <template <typename...> class Template, typename... Args> | |
| struct fill_maintaining_defaults { | |
| private: | |
| using args_list = mp_list<Args...>; | |
| using index_of_first_default = typename find_index_of_first_default<args_list>::type; | |
| using args_before_defaults = mp_take<args_list, index_of_first_default>; | |
| using args_replacing_defaults = mp_drop<args_list, index_of_first_default>; | |
| using default_args = typename get_default_arguments<Template, args_before_defaults>::type; | |
| using default_args_where_placeholders_existed | |
| = typename replace_placeholders_with_default_arguments<args_replacing_defaults, default_args>::type; | |
| using final_args = mp_append<args_before_defaults, default_args_where_placeholders_existed>; | |
| using final_type = mp_rename<final_args, Template>; | |
| public: | |
| using type = final_type; | |
| }; | |
| } | |
| template <template <typename...> class Template, typename... Args> | |
| using with_defaults = typename detail::fill_maintaining_defaults<Template, Args...>::type; | |
| #include <map> | |
| #include <vector> | |
| #include <unordered_map> | |
| #include <set> | |
| static_assert(std::is_same<std::vector<int>, with_defaults<std::vector,int>>::value, ""); | |
| static_assert(std::is_same<std::vector<int>, with_defaults<std::vector,int,_>>::value, ""); | |
| static_assert(std::is_same<std::map<int,int,std::less<int>,std::allocator<std::pair<const int,int>>>, with_defaults<std::map,int,int,_,_>>::value, ""); | |
| static_assert(std::is_same<std::unordered_map<int,int,std::hash<int>,std::equal_to<long>>, with_defaults<std::unordered_map,int,int,_,std::equal_to<long>>>::value, ""); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment