If I am using the following type:
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>;
Would there be anyway I could do something equivalent to this pseudo code:
using newOpts = myOpts[6]<82>;
Which would keep all the existing template arguments and set the 7th one to 82
.
I propose a template using
as follows
template <std::size_t Idx, std::uint64_t NewVal, typename MO>
using NewOpts = decltype(get_new_opt<Idx, NewVal>(std::declval<MO>()));
where get_new_opts()
and get_new_opts_helper()
are declared only helper functions as follows
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)>{}) );
You can use NewOpts
as follows
using new_opt = NewOpts<6u, 82u, myOpts>;
The following is a full compiling (C++14, because uses std::index_sequence
) example
#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, "!" );
}