0

I'm trying to implement something of the form

template<typename ...args> void func(int l, args... arg, int r){ } 

I could use

template<typename ...args> void func(int l, int r, args... arg){ } 

but it would make it far more unintuitive to use. The function itself is

 template<typename ...TA, enable_if_t<sizeof...(TA) == 2 * (d - 1), int> = 0> void upd(int u1, TA... args, T val){ u1 += n; while(u1){ t[u1].upd(args..., val); u1 >>= 1; } } 
4
  • how about void func(int l,std::tuple<args....> arg,int r) ? Commented Mar 3, 2022 at 8:00
  • Please show what should be inside of func. Commented Mar 3, 2022 at 8:01
  • Would that require me to explicitly give the middle argument as a tuple? Commented Mar 3, 2022 at 8:02
  • From where d is given? Commented Mar 3, 2022 at 12:32

1 Answer 1

1

d seems fixed, so it is not really variadic.

You can then have specializations (up to a certain limit)

template <std::size_t d> struct S; template <> struct S<0> { void upd(int u1, T val){ u1 += n; while(u1){ t[u1].upd(val); u1 >>= 1; } } }; template <> struct S<1> { template <typename T1, typename T2> void upd(int u1, T1 t1, T2 t2, T val){ u1 += n; while(u1){ t[u1].upd(T1, t2, val); u1 >>= 1; } } }; //... // struct S<2> // ... // void upd(int u1, T1 t1, T2 t2, T3 t3, T4 t4, T val){ // ... 

If the types T1, TN are fixed (assuming SomeType), one possibility is to use std::index_sequence instead of d

 template <std::size_t, typename T> using always_t = T; template <typename Seq> struct S_impl; template <std::size_t... Is> struct S_impl<std::index_sequence<Is...>> { void upd(int u1, always_t<Is, SomeType>... args, T val){ u1 += n; while(u1) { t[u1].upd(args..., val); u1 >>= 1; } } }; template <std::size_t d> using S = S_impl<std::make_index_sequence<d>>; 

Else, you can use tuple or reordering argument for implementation, and provide wrapper for the interface:

template<std::size_t... Is, typename Tuple> auto extract(std::index_sequence<Is...>, Tuple t) { return std::tie(std::get<Is>(t)...); } template <typename ...Ts, enable_if_t<sizeof...(Ts) == 2 * (d - 1), int> = 0> void upd_impl(int u1, std::tuple<Ts...> tup, T val) { u1 += n; while(u1){ std::apply([&](auto&&... args){ t[u1].upd(args..., val); u1 >>= 1; }, tup } } template <typename ...Ts, enable_if_t<sizeof...(Ts) == 1 + 2 * (d - 1), int> = 0> void upd(int u1, Ts... args) { upd_impl(u1, extract(std::make_index_sequence<sizeof...(Ts) - 1>(), std::tie(args...)), std::get<sizeof...(Ts) - 1>(std::tie(args...))); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.