Skip to content

Instantly share code, notes, and snippets.

@notfoundry
Created May 26, 2018 15:35
Show Gist options
  • Select an option

  • Save notfoundry/25d0a55067e111c5fb15442839639d28 to your computer and use it in GitHub Desktop.

Select an option

Save notfoundry/25d0a55067e111c5fb15442839639d28 to your computer and use it in GitHub Desktop.
Keep some default template parameters of a type while replacing others
#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