Parameter pack expansion for static variables

user4663214

I am thinking about following problem:

Let us have a merging function for merge arrays defined in following way:

// input is (const void*, size_t,  const void*, size_t,...)
template<typename...ARGS>
MyArray Concatenation(ARGS...args)

And let us have couple of structs with static properties

struct A { static void* DATA; static size_t SIZE; };
struct B { static void* DATA; static size_t SIZE; };
struct C { static void* DATA; static size_t SIZE; };

I would like to have a method:

template<typename...ARGS>
MyArray AutoConcatenation();

Where ARGS should be structs with mentioned static interface. Following methods should have the same output:

AutoConcatenation<A, B, C>();
Concatenation(A::DATA, A::SIZE, B::DATA, B::SIZE, C::DATA, C::SIZE);

My question is how to implement parameter pack expansion.

I tried:

// not working
template<typename...ARGS>
MyArray AutoConcatenation()
{
  return Concatenation((ARGS::DATA, ARGS::SIZE)...);
}

What about expansions

ARGS::DATA... // Correct expansion of pointers
ARGS::SIZE... // Correct expansion of sizes
(ARGS::DATA, ARGS::SIZE)... // Seems to be expansion of sizes

Just info for advisors. I am looking for implementation of AutoConcatenation method, not for its redeclaration nor for redeclaration previous code, thank you.

bogdan

A lazy solution using std::tuple:

  • make a tuple of DATA and SIZE for each element of the parameter pack,
  • flatten the list of tuples to one big tuple using std::tuple_cat,
  • apply the resulting tuple's elements to Concatenation by expanding a list of indexes in an std::index_sequence.

In the following code, the test harness is longer than the actual solution:

#include <cstddef>
#include <tuple>
#include <utility>
#include <iostream>
#include <typeinfo>
#include <type_traits>

struct MyArray { };
template<class... ARGS> MyArray Concatenation(ARGS... args) 
{
   // Just some dummy code for testing.
   using arr = int[];
   (void)arr{(std::cout << typeid(args).name() << ' ' << args << '\n' , 0)...};
   return {}; 
}

struct A { static void* DATA; static std::size_t SIZE; };
struct B { static void* DATA; static std::size_t SIZE; };
struct C { static void* DATA; static std::size_t SIZE; };

// Also needed for testing.
void* A::DATA;
std::size_t A::SIZE;
void* B::DATA;
std::size_t B::SIZE;
void* C::DATA;
std::size_t C::SIZE;


// The useful stuff starts here.

template<class T, std::size_t... Is> MyArray concat_hlp_2(const T& tup, std::index_sequence<Is...>)
{
   return Concatenation(std::get<Is>(tup)...);
}

template<class T> MyArray concat_hlp_1(const T& tup)
{
   return concat_hlp_2(tup, std::make_index_sequence<std::tuple_size<T>::value>{});
}

template<class... ARGS> MyArray AutoConcatenation()
{
   return concat_hlp_1(std::tuple_cat(std::make_tuple(ARGS::DATA, ARGS::SIZE)...));
}


int main()
{
   AutoConcatenation<A, B, C>();
}

If you want to avoid std::tuple and std::tuple_cat (which can be heavy in terms of compile times), here's an alternative using indexes into arrays.

The testing code stays the same, this is just the juicy stuff:

template<std::size_t Size> const void* select(std::false_type, std::size_t idx,
   const void* (& arr_data)[Size], std::size_t (&)[Size])
{
   return arr_data[idx];
}

template<std::size_t Size> std::size_t select(std::true_type, std::size_t idx,
   const void* (&)[Size], std::size_t (& arr_size)[Size])
{
   return arr_size[idx];
}

template<std::size_t... Is> MyArray concat_hlp(std::index_sequence<Is...>, 
   const void* (&& arr_data)[sizeof...(Is) / 2], std::size_t (&& arr_size)[sizeof...(Is) / 2])
{
   return Concatenation(select(std::bool_constant<Is % 2>{}, Is / 2, arr_data, arr_size)...);
}

template<class... ARGS> MyArray AutoConcatenation()
{
   return concat_hlp(std::make_index_sequence<sizeof...(ARGS) * 2>{}, {ARGS::DATA...}, {ARGS::SIZE...});
}

Again a sequence of indexes twice the size of the original parameter pack, but we build separate arrays of DATA and SIZE and then use tag dispatching to select elements from one or the other depending on the parity of the current index.

This may not look as nice as the previous code, but it doesn't involve any template recursion (std::make_index_sequence is implemented using compiler intrinsics in modern compilers as far as I know) and cuts down on the number of template instantiations, so it should be faster to compile.

The select helper can be made constexpr by using arrays of pointers to the static members, but this turns out to be unnecessary in practice. I've tested MSVC 2015 U2, Clang 3.8.0 and GCC 6.1.0 and they all optimize this to a direct call to Concatenation (just like for the tuple-based solution).

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Parameter pack expansion fails

From Dev

Parameter pack expansion questions

From Dev

Simple parameter pack expansion: expected ';'

From Dev

parameter pack expansion not working in lambda

From Dev

Initializing std::array with Static Storage Duration with a Parameter Pack Expansion and an Additional Value

From Dev

Initializing std::array with Static Storage Duration with a Parameter Pack Expansion and an Additional Value

From Dev

Parameter expansion on multiple variables

From Dev

Empty parameter pack expansion different to manual empty parameter pack

From Java

Problem with order of evaluation in parameter pack expansion

From Dev

Add all parameters with parameter pack expansion

From Dev

What is the syntax for parameter pack expansion with alignas?

From Dev

a variadic template as a template parameter without pack expansion

From Dev

Templates. Parameter pack expansion - remap types

From Dev

Definition of "pattern" for parameter pack expansion, especially within a function call

From Dev

C++: parameter pack expansion inside lambda fails

From Dev

Parameter pack expansion within parentheses gives bizarre output

From Dev

Clang fails to compile parameter pack expansion using template metaprogramming

From Dev

when template parameter of a template template-parameter is pack expansion, gcc fails, clang succeeds

From Dev

Variadic template pack expansion

From Dev

Arithmetic expansion and parameter expansion

From Dev

Return type which depends on static parameter pack fields

From Dev

Expand struct type template parameter pack in its static recursive function

From Dev

Why does parameter pack expansion work differently with different C++ compilers?

From Dev

I've found a parameter pack expansion here on the board and I don't understand what exactly is going

From Dev

Variadic template indexed pack expansion

From Dev

How do you static_assert the values in a parameter pack of a variadic template?

From Dev

: and := inside a bash parameter expansion

From Dev

Parameter Expansion With Python

From Dev

Parameter expansion in grep

Related Related

  1. 1

    Parameter pack expansion fails

  2. 2

    Parameter pack expansion questions

  3. 3

    Simple parameter pack expansion: expected ';'

  4. 4

    parameter pack expansion not working in lambda

  5. 5

    Initializing std::array with Static Storage Duration with a Parameter Pack Expansion and an Additional Value

  6. 6

    Initializing std::array with Static Storage Duration with a Parameter Pack Expansion and an Additional Value

  7. 7

    Parameter expansion on multiple variables

  8. 8

    Empty parameter pack expansion different to manual empty parameter pack

  9. 9

    Problem with order of evaluation in parameter pack expansion

  10. 10

    Add all parameters with parameter pack expansion

  11. 11

    What is the syntax for parameter pack expansion with alignas?

  12. 12

    a variadic template as a template parameter without pack expansion

  13. 13

    Templates. Parameter pack expansion - remap types

  14. 14

    Definition of "pattern" for parameter pack expansion, especially within a function call

  15. 15

    C++: parameter pack expansion inside lambda fails

  16. 16

    Parameter pack expansion within parentheses gives bizarre output

  17. 17

    Clang fails to compile parameter pack expansion using template metaprogramming

  18. 18

    when template parameter of a template template-parameter is pack expansion, gcc fails, clang succeeds

  19. 19

    Variadic template pack expansion

  20. 20

    Arithmetic expansion and parameter expansion

  21. 21

    Return type which depends on static parameter pack fields

  22. 22

    Expand struct type template parameter pack in its static recursive function

  23. 23

    Why does parameter pack expansion work differently with different C++ compilers?

  24. 24

    I've found a parameter pack expansion here on the board and I don't understand what exactly is going

  25. 25

    Variadic template indexed pack expansion

  26. 26

    How do you static_assert the values in a parameter pack of a variadic template?

  27. 27

    : and := inside a bash parameter expansion

  28. 28

    Parameter Expansion With Python

  29. 29

    Parameter expansion in grep

HotTag

Archive