C++ using a template parameter pack to invoke multiple templated functions

Charlie

Dear internet people,

I'm currently writing a variant class in C++14 and needed to call a template function for each element in the parameter pack. After some searching I came across this page which features the following sample.

template<typename... Ts> void func(Ts... args){
    const int size = sizeof...(args) + 2;
    int res[size] = {1,args...,2};
    // since initializer lists guarantee sequencing, this can be used to
    // call a function on each element of a pack, in order:
    int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... };
}

I created this small example which demonstrates what I'm trying to achieve.

#include <iostream>

template<typename Ta, typename Tb> struct TypeCmp
{
    static constexpr bool Value = false;
};

template<typename T> struct TypeCmp<T, T>
{
    static constexpr bool Value = true;
};

template<typename T, typename... Ts> struct TypeIdCounter;

template<typename T> struct TypeIdCounter<T>
{
    static constexpr size_t Value = 1;
};

template<typename T, typename Tcur, typename... Ts> struct TypeIdCounter<T, Tcur, Ts...>
{
    static constexpr size_t Value = sizeof(Tcur)+(TypeCmp<T, Tcur>::Value ? 0 : TypeIdCounter<T, Ts...>::Value);
};

template<typename... Ts> struct TypeHolder
{
    template<typename T> struct Info
    {
        static constexpr size_t Id = TypeIdCounter<T, Ts...>::Value;
        static constexpr size_t Size = sizeof(T);

        static void Print(size_t id)
        {
            if (Id == id)
            {
                std::cout << "Type::Id = " << Id << std::endl;
                std::cout << "Type::Size = " << Size << std::endl;
            }
        }
    };

    template<typename T> TypeHolder(const T& value) : id(Info<T>::Id)
    {
        /* copy value to container */
    }

    void Print() const
    {
        int dummy[] = {(Info<Ts>::Print(id), 0)...};
        if (dummy[0])
        {
            /* dummy test needed! */
        }
    }

    size_t id;
};

struct Foo
{
    std::string name;
    int age;
};

typedef TypeHolder<int, long long, bool, Foo> MyTypes;

int main(int argc, char* args[])
{
    std::cout << "Id(int): " << MyTypes::Info<int>::Id << std::endl;
    std::cout << "Id(bool): " << MyTypes::Info<bool>::Id << std::endl;
    std::cout << "Id(Foo): " << MyTypes::Info<Foo>::Id << std::endl;

    MyTypes types(true);

    types.Print();

    return 0;
}

The program listed above generates the following output.

Id(int): 4
Id(bool): 13
Id(Foo): 53
Type::Id = 13
Type::Size = 1

As always I compile my code with the -Wall -Werror flags. So the if (dummy[0])... condition is needed or else I get a unused variable 'dummy' error.

I'm totally clueless why int dummy[] = {(Info<Ts>::Print(id), 0)...}; seems to work since Info::Print is a void method. Could someone enlighten me and explain why this works? And is there a way to prevent the int dummy[] = {(...)}; if (dummy[0]); trick without dropping -Wall -Werror?

I have been trying to search for a explanation but since I have no idea what this construction is even called it's not easy to find anything.

Yakk - Adam Nevraumont
using dummy=int[];
(void)dummy{0,
  ((void)(Info<Ts>::Print(id)), 0)...
};

will replace

int dummy[] = {(Info<Ts>::Print(id), 0)...};

and should not generate any warnings. It also handles 0-length lists.

The , operator will take void types. It is built-in, and magic.

The use of (void) next to Print above ensures that if the return type of Print is non-void, and that return type overloads operator,(blah, 0), we don't get unexpected behavior.

Myself, on compilers that support it, I write invoke_for_each.

template<class T>struct tag_type{using type=T;};
template<class T>constexpr tag_type<T> tag{};

template<class F, class...Ts>
void invoke_for_each( F&& f, Ts&&...ts ) {
  using dummy=int[];
  (void)dummy{0,
    ((void)(f(std::forward<Ts>(ts)), 0)...
  };
};

and now at point of use:

invoke_for_each(
  [&](auto tag){
    using T=typename decltype(tag)::type;
    Info<T>::Print(id);
  },
  tag<Ts>...
);

where we move the magic array stuff out of view of the person reading the code.

Collected from the Internet

Please contact debug[email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Multiple Variadic Parameter Pack for Template Class

From Dev

Using a class as a template parameter for a templated class with forward declaration

From Dev

Multiple functions using the same template?

From Dev

Multiple functions using the same template?

From Dev

Using same parameter for multiple functions

From Dev

Clang fails to compile parameter pack expansion using template metaprogramming

From Dev

Use a templated variadic template parameter as specialized parameter

From Dev

Compile time array from C++ template parameter pack

From Dev

c++ Unpacking parameter pack from template arguments

From Dev

C++ - specialize function template on a templated class with a non type template parameter

From Dev

Inspect template parameter pack in gdb

From Dev

Parameter pack with default template argument

From Dev

Cumulative Product of Template Parameter Pack

From Dev

Specialize on default template parameter pack

From Dev

Dynamically build a template parameter pack

From Dev

Distribute argument parameter pack to invoke two functors

From Dev

reducing code using templated functions

From Dev

Using a range as a parameter pack

From Dev

Passing a templated smart pointer type as template parameter

From Dev

Overloading of C++ templated functions

From Dev

a variadic template as a template parameter without pack expansion

From Dev

Function template parameter pack not at the end of the parameter list

From Dev

How to invoke multiple functions/chained calls using ng-click

From Dev

Listener Pattern via Templates, how to use templated class without specifying template parameter? c++

From Dev

C++ passing template parameter pack from one variadic template to another causes compiler error

From Dev

multiple functions with same name but different argument types as template parameter

From Dev

templated type with no template variable and other templated type using such

From Dev

Is there a way to pass templated function signature as a template template parameter

From Dev

Using function template as template template parameter in C++

Related Related

  1. 1

    Multiple Variadic Parameter Pack for Template Class

  2. 2

    Using a class as a template parameter for a templated class with forward declaration

  3. 3

    Multiple functions using the same template?

  4. 4

    Multiple functions using the same template?

  5. 5

    Using same parameter for multiple functions

  6. 6

    Clang fails to compile parameter pack expansion using template metaprogramming

  7. 7

    Use a templated variadic template parameter as specialized parameter

  8. 8

    Compile time array from C++ template parameter pack

  9. 9

    c++ Unpacking parameter pack from template arguments

  10. 10

    C++ - specialize function template on a templated class with a non type template parameter

  11. 11

    Inspect template parameter pack in gdb

  12. 12

    Parameter pack with default template argument

  13. 13

    Cumulative Product of Template Parameter Pack

  14. 14

    Specialize on default template parameter pack

  15. 15

    Dynamically build a template parameter pack

  16. 16

    Distribute argument parameter pack to invoke two functors

  17. 17

    reducing code using templated functions

  18. 18

    Using a range as a parameter pack

  19. 19

    Passing a templated smart pointer type as template parameter

  20. 20

    Overloading of C++ templated functions

  21. 21

    a variadic template as a template parameter without pack expansion

  22. 22

    Function template parameter pack not at the end of the parameter list

  23. 23

    How to invoke multiple functions/chained calls using ng-click

  24. 24

    Listener Pattern via Templates, how to use templated class without specifying template parameter? c++

  25. 25

    C++ passing template parameter pack from one variadic template to another causes compiler error

  26. 26

    multiple functions with same name but different argument types as template parameter

  27. 27

    templated type with no template variable and other templated type using such

  28. 28

    Is there a way to pass templated function signature as a template template parameter

  29. 29

    Using function template as template template parameter in C++

HotTag

Archive