Home > Software engineering >  Passing variadic template arguments to another template
Passing variadic template arguments to another template

Time:01-25

I have this code in which static_for can be used as a compile-time loop using template-metaprogramming and loop_types is a struct accepting variadic arguments. Whenever I try to call the function call, it give me an error.

In loop_types, the is a template loop contain the function that prints name of the types.


//Template specialization for getting an index of variadic template
template <unsigned long long index, typename... P>
struct variadic_type_template_index;

template <typename T,typename... P>
struct variadic_type_template_index<0,T,P...>
{
    using type = T;
};

template <unsigned long long index,typename T,typename... P>
struct variadic_type_template_index<index,T,P...>
{
    using type = variadic_type_template_index<index-1,P...>::type;
};

template <unsigned long long index,typename... T>
using variadic_type_template_index_t = variadic_type_template_index<index,T...>::type;




//Rest of the program

#include <stdlib.h> // For malloc
#include <iostream> // For std::cout

template <template <unsigned long long,unsigned long long> typename tocall,unsigned long long initval,unsigned long long times>
struct static_for;


template <template <unsigned long long,unsigned long long> typename tocall,unsigned long long initval,unsigned long long times>
requires requires(){tocall<initval,times>::toCall();}
struct static_for<tocall,initval,times>
{
    static_assert(initval<times,"Invalid static_for loop");
    constexpr static void call()
    {
        tocall<initval,times>::toCall();
        static_for<tocall,initval  1,times>::call();
    }
};
template <template <unsigned long long,unsigned long long> typename tocall,unsigned long long val>
struct static_for<tocall,val,val>
{
    constexpr static void call()
    {}
};

template <typename... Args>
struct loop_types
{
    template <unsigned long long i,unsigned long long t>
    struct loop
    {
        using type = variadic_type_template_index_t<i,Args...>;
        static void toCall()
        {
            std::cout<<typeid(type).name()<<"\n";
        }
    };
};

template <typename... Args>
void call(Args...)
{
    static_for<loop_types<Args...>::loop,0,sizeof...(Args)>::call();
}


int main()
{
    call("1",2,true,malloc(5));
}

Error message I get

ToRun.cpp: In function 'void call(Args ...)':
ToRun.cpp:67:59: error: type/value mismatch at argument 1 in template parameter list for 'template<template<long long unsigned int <anonymous>, long long unsigned int <anonymous> > class tocall, long long unsigned int initval, long long unsigned int times> struct static_for'
   67 |     static_for<loop_types<Args...>::loop,0,sizeof...(Args)>::call();
      |                                                           ^
ToRun.cpp:67:59: note:   expected a class template, got 'loop_types<Args ...>::loop'
ToRun.cpp:67:66: warning: empty parentheses were disambiguated as a function declaration [-Wvexing-parse]
   67 |     static_for<loop_types<Args...>::loop,0,sizeof...(Args)>::call();
      |                                                                  ^~
ToRun.cpp:67:66: note: remove parentheses to default-initialize a variable
   67 |     static_for<loop_types<Args...>::loop,0,sizeof...(Args)>::call();
      |                                                                  ^~
      |                                                                  --
ToRun.cpp:67:66: note: or replace parentheses with braces to value-initialize a variable

How can I fix this problem?

Also, in case I replace Args... with a number of types ifself like with int,char,bool along with specifying number of types itself, the code works properly.

Compiler used - GCC

Command used

g   ToRun.cpp -o ToRun -std=c  23 && "ToRun.exe"

I was expecting the program to print the types' name of every parameter I passes to call

CodePudding user response:

For call() function... passing through a using should solve the problem

template <typename... Args>
void call(Args...)
{
  using for_t = static_for<loop_types<Args...>::template loop, 0, sizeof...(Args)>;

  for_t::call();
}

but remember to add a couple of typename in variadic_type_template_index specialization and using

template <unsigned long long index,typename T,typename... P>
struct variadic_type_template_index<index,T,P...>
{
    using type = typename variadic_type_template_index<index-1,P...>::type;
    // ..........^^^^^^^^
};

template <unsigned long long index,typename... T>
using variadic_type_template_index_t = typename variadic_type_template_index<index,T...>::type;
// ....................................^^^^^^^^

and also a dummy variadic_type_template_index<0> specialization, by example

template <>
struct variadic_type_template_index<0>
{
    using type = void;
};

or you get a compilation error from

requires requires(){tocall<initval,times>::toCall();}

when initval is equal to times

  • Related