Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
182 views
in Technique[技术] by (71.8m points)

c++ - Is there a way to define a variadic number of arguments of the same type?

I can't figure out how to implement a function with a variable number of arguments of the same type.

I'm writing for a microcontroller with little stack and memory, so I can't use recursion or the STL (the parts with exceptions).

Is it possible to make such a function?

struct S{
int r1;
int r2;
};
template<S* s, int... args> fun(int arg1, int arg2);

which expands to something like this:

for(int arg:args){ 
s->r1+=7*arg;
}

example of invocation:

S s;
const int mode=3, speed=1;

fun<&s,1,2,7,4>(mode,speed);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I can't figure out how to implement a function with a variable number of arguments of the same type.

Template argument of the same type or ordinary function arguments of the same type?

The first case is simple (if the type is one admitted for template value types), exactly as you have written

template<S* s, int... args>
fun (int arg1, int arg2);

and you can use they using template folding, if you can use C++17,

template <S* s, int... args>
auto fun (int arg1, int arg2)
 { ((s->r1 += 7 * args), ...); }

or in a little more complicated way before (C++11/C++14)

template <S* s, int... args>
auto fun (int arg1, int arg2)
 { 
   using unused = int[];

   (void)unused { 0, s->r1 += 7 * args ... };
 }

Unfortunately you can call this type of function with compile time known integers so, by example, not with variables

int a = 7;
fun<&s,1,2,a,4>(mode,speed); // compilation error

In this case you need a variadic list of ordinary function arguments of the same type; unfortunately this is a little more complicated.

You can create a typical variadic list of template parameter

template <typename ... Args>
auto fun (Args ... args)

imposing, through SFINAE, that all Args... are deduced or explicated as int (see Michael Kenzel's answer).

Unfortunately this require that every argument is exactly if type int so calling func with (by example) a long int gives a compilation error

fun(1, 2, 3l); // compilation error (3l is a long int, not an int)

Obviously you can relax the SFINAE condition imposing (by example) that all Args... types are convertible (std::is_convertible) to int but isn't exactly has developing a function receiving a variadic number of arguments of the same type.

If you can accept a superior limit to the number of arguments (64, in the following example) and that the function is method (maybe static) of a class, you can create a foo class containing a method f() that receive zero int, one f() that receive one int, one f() that receive two ints, etc, until an f() that receive 63 ints.

The following is a full compiling C++17 example

#include <utility>
#include <type_traits>

struct S
{
    int r1;
    int r2;
};

S s;
const int mode=3, speed=1;

template <typename T, std::size_t>
using getType = T;

template <std::size_t N, typename = std::make_index_sequence<N>>
struct bar;

template <std::size_t N, std::size_t ... Is>
struct bar<N, std::index_sequence<Is...>>
 {
   static constexpr auto f (getType<int, Is> ... args)
    { ((s.r1 += 7 * args), ...); }
 };

template <S &, std::size_t N = 64u, typename = std::make_index_sequence<N>>
struct foo;

template <S & s, std::size_t N, std::size_t ... Is>
struct foo<s, N, std::index_sequence<Is...>> : public bar<Is>...
 { using bar<Is>::f...; };

int main ()
 {
   foo<s>::f(mode, speed);
 }

In C++14 is a little more complicated because there isn't variadic using so you have to write the foo class in a recursive way.

In C++11 you have also to develop a substitute for std::make_index_sequence/std::index_sequence.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...