如何更改 C++ 中的第 n 个模板参数?

How to change the nth template parameter in C++?

如果我使用以下类型:

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>;

这将保留所有现有的模板参数并将第 7 个设置为 82

我提出一个模板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, "!" );
 }