Я предлагаю шаблон using
следующим образом
template <std::size_t Idx, std::uint64_t NewVal, typename MO>
using NewOpts = decltype(get_new_opt<Idx, NewVal>(std::declval<MO>()));
, где get_new_opts()
и get_new_opts_helper()
объявлены только вспомогательные функции следующим образом
template <std::size_t Idx, std::uint64_t NewVal, std::uint64_t ... Fs,
std::size_t ... Is>
constexpr auto get_new_opt_helper (Options<Fs...>,
std::index_sequence<Is...>)
-> std::remove_reference_t<
decltype( std::declval<Options<(Idx == Is ? NewVal : Fs)...>>() )>;
template <std::size_t Idx, std::uint64_t NewVal, std::uint64_t ... Fs>
constexpr auto get_new_opt (Options<Fs...> o)
-> decltype( get_new_opt_helper<Idx, NewVal>
(o, std::make_index_sequence<sizeof...(Fs)>{}) );
Вы можете использовать NewOpts
следующим образом
using new_opt = NewOpts<6u, 82u, myOpts>;
Ниже приводится полная компиляция (C ++ 14, потому что используется std::index_sequence
), пример
#include <cstdint>
#include <utility>
template <std::uint64_t f1 = 0u, std::uint64_t f2 = 0u, std::uint64_t f3 = 0u,
std::uint64_t f4 = 0u, std::uint64_t f5 = 0u, std::uint64_t f6 = 0u,
std::uint64_t f7 = 0u, std::uint64_t f8 = 0u, std::uint64_t f9 = 0u,
std::uint64_t f10 = 0u>
class Options
{ };
template <std::size_t Idx, std::uint64_t NewVal, std::uint64_t ... Fs,
std::size_t ... Is>
constexpr auto get_new_opt_helper (Options<Fs...>,
std::index_sequence<Is...>)
-> std::remove_reference_t<
decltype( std::declval<Options<(Idx == Is ? NewVal : Fs)...>>() )>;
template <std::size_t Idx, std::uint64_t NewVal, std::uint64_t ... Fs>
constexpr auto get_new_opt (Options<Fs...> o)
-> decltype( get_new_opt_helper<Idx, NewVal>
(o, std::make_index_sequence<sizeof...(Fs)>{}) );
template <std::size_t Idx, std::uint64_t NewVal, typename MO>
using NewOpts = decltype(get_new_opt<Idx, NewVal>(std::declval<MO>()));
int main ()
{
using myOpts = Options<51u, 8u, 12u>;
using new_opt = NewOpts<6u, 82u, myOpts>;
using target_opt = Options<51u, 8u, 12u, 0u, 0u, 0u, 82u>;
static_assert( std::is_same<new_opt, target_opt>::value, "!" );
}