Как изменить n-й параметр шаблона в C ++? - PullRequest
0 голосов
/ 15 февраля 2019

Если я использую следующий тип:

template<uint64_t f1 = 0, uint64_t f2 = 0, uint64_t f3 = 0, ..., uint64_t f10 = 0>
class Options;

using myOpts = Options<51, 8, 12>;

Будет ли в любом случае я мог бы сделать что-то эквивалентное этому псевдокоду:

using newOpts = myOpts[6]<82>;

, который сохранит весь существующий шаблонаргументы и установите седьмой на 82.

1 Ответ

0 голосов
/ 15 февраля 2019

Я предлагаю шаблон 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, "!" );
 }
...