How to reverse the order of arguments of a variadic template function?
Here is a recursive implementation of a specialized revert<>
:
// forward decl
template<class ...Tn>
struct revert;
// recursion anchor
template<>
struct revert<>
{
template<class ...Un>
static void apply(Un const&... un)
{
ascendingPrint(un...);
}
};
// recursion
template<class T, class ...Tn>
struct revert<T, Tn...>
{
template<class ...Un>
static void apply(T const& t, Tn const&... tn, Un const&... un)
{
// bubble 1st parameter backwards
revert<Tn...>::apply(tn..., t, un...);
}
};
// using recursive function
template<class A, class ...An>
void descendingPrint(A const& a, An const&... an)
{
revert<An...>::apply(an..., a);
}
It works with gcc-4.6/7/8 and clang and is probably standard compliant -- the only difficult part being the call of revert<Tn...>::apply(tn..., t, un...)
.
It has drawbacks though (as recursion often has), that it generates a lot of template-instantiations of the target function (code bloat) and does not use perfect forwarding, which may be an issue (but maybe could be improved to use it).
Reverse variadic template arguments in hierarchy
If all the types in the pack are distinct, you can compute the type's index
from the type itself. All that remains is to extract the N - 1 - index
'th type from the pack:
template<std::size_t index, class... Ts>
using Nth_type = std::tuple_element_t<index, std::tuple<Ts...>>;
template<class S, class... Ts>
inline constexpr std::size_t type_index = 0;
template<class S, class T, class... Ts>
inline constexpr std::size_t type_index<S, T, Ts...> =
std::is_same_v<S, T> ? 0 : 1 + type_index<S, Ts...>;
template<class T, class... Ts>
using Reverser = Nth_type<sizeof...(Ts) - 1 - type_index<T, Ts...>, Ts...>;
Simple example:
template<class... Ts>
class B;
template<class... Ts>
using RB = B<Reverser<Ts, Ts...>...>; // two pack expansions here
static_assert(std::is_same<RB<>, B<>>());
static_assert(std::is_same<RB<int>, B<int>>());
static_assert(std::is_same<RB<int, float, double>, B<double, float, int>>());
If the pack is allowed to contain identical types, this trick won't work.
This code uses some C++14/17 features. Variable templates are not part of C++11, so type_index
has to be implemented differently. Here is a possible implementation.
Iterate in reverse order through the parameter-pack of a variadic template function
Because you should provide, well, template declaration before specializations:
#include <iostream>
template<typename...> void f();
template<>
void f() {}
template<int H, int... T>
void f()
{
f<T...>();
std::cout << H << std::endl;
}
int main()
{
f<1,2,3,42,5>();
return 0;
}
Here we go: https://ideone.com/TZal7p
Reverse order of varidic template arguments while constructing a map key
Since C++17 I would use fold expression (op,...)
to do that:
template<class B, class ... Args>
auto key(B base, Args ... args) {
std::common_type_t<Args...> res{};
( (res *= base, res += args % base), ... );
return res;
}
Demo
Does variadic template function call lambda parameter in reverse order?
When an expression that contains a pack expansion is evaluated, the pack is expanded first---which simply instantiates the code, so to speak, without performing any evaluation---then the resulting expression is evaluated according to the usual rules. Your expression
[&](...){}(
(fib(),123)...
);
is expanded into
[&](...){}(
(f1(),123), (f2(),123)
);
and since function arguments are evaluated in an unspecified order, you cannot rely on f2
being called before f1
or vice versa.
Iterating variadic template arguments in reverse order
You're missing a typedef
in Mapped_scope_deep_r
. This line declares an object, not a type:
typename Mapped_scope_deep_r< typename boost::mpl::at<map, HeadTag>::type::type_map, TailTag...>::type type;
As for reversing the order of a pack, there are some dirty tricks, but the best way is to define a metafunction tuple_reverse
and use it to filter the template's input.
How to reverse an integer parameter pack?
How can I reverse the parameter
pack <5, 1, 0>
to<0, 1, 5>
without using any std library functions?
Not sure to understand what do you exactly can use but... it seems easy to me.
Given an helper struct as follows
template <typename, typename>
struct RS_helper;
template <int ... As, int B0, int ... Bs>
struct RS_helper<MetaSequenceOfIntegers<As...>,
MetaSequenceOfIntegers<B0, Bs...>>
: RS_helper<MetaSequenceOfIntegers<B0, As...>,
MetaSequenceOfIntegers<Bs...>>
{ };
template <typename T>
struct RS_helper<T, MetaSequenceOfIntegers<>>
{ using type = T; };
the revert struct can be simply
template <int ... Is>
struct RevertSequence
: RS_helper<MetaSequenceOfIntegers<>, MetaSequenceOfIntegers<Is...>>
{ };
I suppose that a reverse function can be useful
template <int ... Is>
constexpr typename RevertSequence<Is...>::type
revertSequenceFunction (MetaSequenceOfIntegers<Is...> const &)
{ return {}; }
I propose a modified version of your original code with addition of reversed sequence (using also std::cout
to print the sequences, but you can remove it, obviously).
#include <iostream>
template <int ...>
struct MetaSequenceOfIntegers
{ };
template <int AccumulatedSize, typename Tn, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence;
template <int AccumulatedSize, typename Grouper, typename Head,
typename ... Tail, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(Head, Tail...),
GeneratedSequence... >
{ typedef typename GeneratorOfIntegerSequence
<AccumulatedSize+sizeof(Head), Grouper(Tail...),
AccumulatedSize, GeneratedSequence...>::type type; };
template <int AccumulatedSize, typename Grouper, int ... GeneratedSequence>
struct GeneratorOfIntegerSequence<AccumulatedSize, Grouper(),
GeneratedSequence...>
{ typedef MetaSequenceOfIntegers<GeneratedSequence...> type; };
template <int ... Sequence>
void intergers_sequencer_generator(MetaSequenceOfIntegers<Sequence...>)
{
using unused = int[];
(void)unused { 0, (std::cout << Sequence << ' ', 0)... };
std::cout << std::endl;
}
template <typename, typename>
struct RS_helper;
template <int ... As, int B0, int ... Bs>
struct RS_helper<MetaSequenceOfIntegers<As...>,
MetaSequenceOfIntegers<B0, Bs...>>
: RS_helper<MetaSequenceOfIntegers<B0, As...>,
MetaSequenceOfIntegers<Bs...>>
{ };
template <typename T>
struct RS_helper<T, MetaSequenceOfIntegers<>>
{ using type = T; };
template <int ... Is>
struct RevertSequence
: RS_helper<MetaSequenceOfIntegers<>, MetaSequenceOfIntegers<Is...>>
{ };
template <int ... Is>
constexpr typename RevertSequence<Is...>::type
revertSequenceFunction (MetaSequenceOfIntegers<Is...> const &)
{ return {}; }
int main ()
{
intergers_sequencer_generator(
GeneratorOfIntegerSequence<0, int(char, int, char)>::type());
intergers_sequencer_generator(
revertSequenceFunction(
GeneratorOfIntegerSequence<0, int(char, int, char)>::type()));
}
How do I iterate (recurse) backwards through a variadic list of template parameters?
This is simple enough to do with an alteration to your Find
structure to return the largest matching index instead of the first such (Live at Coliru):
template<typename... Ts>
struct List{
typedef List<Ts...> Type;
enum {
size = sizeof...(Ts)
};
};
template<int I>
using IntType = std::integral_constant<int, I>;
namespace Detail {
template <typename T, typename U>
struct Max : IntType<(U::value > T::value) ? U::value : T::value> {};
template<int I, typename T, typename... Ts>
struct FindLast : IntType<-1>{};
template<int I, typename T, typename U, typename... Ts>
struct FindLast<I, T, U, Ts...> : FindLast<I + 1, T, Ts...>{};
template<int I, typename T, typename... Ts>
struct FindLast<I, T, T, Ts...> : Max<IntType<I>, FindLast<I + 1, T, Ts...>> {};
}
template<typename T, typename U>
struct FindLast;
template<typename T, typename... Ts>
struct FindLast<T, List<Ts...>> : Detail::FindLast<0, T, Ts...>{};
Backward variadic template
As T.C.'s comment below points out, in your first example aa
is in a non-deduced context (14.8.2.5 p5 defines non-deduced contexts, including "a function parameter pack that does not occur at the end of the parameter-declaration-list") and so the parameter pack cannot be deduced.
if syntax allows for placing variadic arguments in any place other then the last and under what circumstances?
In addition to the restriction stated above that caused problems for your first example, a template parameter pack has to be the last template parameter unless all following template parameters can be deduced. 14.1 [temp.param] p11:
A template parameter pack of a function template shall not be followed
by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2).
So this is OK because both template parameter packs can be deduced independently from the function parameters:
template<typename... T, typename... U>
void f(std::tuple<T...>, std::tuple<U...>)
{ }
A different way to write your shift
function is to use an index_sequence
#include <tuple>
#include <iostream>
template<typename... T, size_t... I>
void
shift_impl(std::tuple<T...> t, std::index_sequence<I...>)
{
// Use pack expansion with comma operator to populate unused array:
int dummy[] = {
(std::get<I>(t) = std::get<I+1>(t), 0)...
};
}
template<typename T0, typename... T>
void
shift(T0&& arg0, T&&... args)
{
shift_impl(std::tie(arg0, args...), std::index_sequence_for<T...>{});
}
int main()
{
int i = 0, j = 1, k = 2;
shift(i, j, k);
std::cout << i << ' ' << j << ' ' << k << '\n';
}
Related Topics
Constexpr Initializing Static Member Using Static Function
How to See the Assembly Code for a C++ Program
How to Draw Text Using Only Opengl Methods
How Is the C++ Exception Handling Runtime Implemented
Remove an Array Element and Shift the Remaining Ones
C++ Data Alignment /Member Order & Inheritance
Why Don't the Std::Fstream Classes Take a Std::String
Identifier Not Found Error on Function Call
How to Use Something Like Std::Vector<Std::Mutex>
G++ Does Not Show a 'Unused' Warning
.C VS .Cc VS. .Cpp VS .Hpp VS .H VS .Cxx
How to Calculate a Time Difference in C++
Are Virtual Destructors Inherited
What Are the Differences Between Overriding Virtual Functions and Hiding Non-Virtual Functions