有没有一种方法可以定义相同类型的各种参数? [英] Is there a way to define a variadic number of arguments of the same type?

查看:64
本文介绍了有没有一种方法可以定义相同类型的各种参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道如何用可变数量的相同类型的参数来实现一个函数。

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

我正在写一个堆栈很少的微控制器和内存,所以我不能使用递归或STL(有异常的部分)。

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);

它会扩展为以下形式:

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

调用示例:

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

fun<&s,1,2,7,4>(mode,speed);


推荐答案


我不能找出如何实现具有可变数量的相同类型参数的函数。

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);

如果可以使用C ++ 17,则可以通过模板折叠来使用它们,

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), ...); }

或之前(C ++ 11 / C ++ 14)

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)

通过SFINAE强制所有 Args ... 被推导或解释为 int (请参阅迈克尔·肯泽尔的答案)。

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

不幸的是,这要求每个参数都必须正确输入类型是否为 int ,因此(例如)使用 long int调用func 给出编译错误

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)

显然,您可以放宽SFINAE条件(例如)强加所有 Args ... 类型都可以转换( std :: is_convertible )到 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.

如果可以的话接受更高的参数数量限制(在以下示例中为 64 ),并且该函数是类的方法(可能是静态的),您可以创建 foo 类,其中包含方法 f()接受零 int ,一个 f()接收一个 int ,一个 f()接收两个 int 等,直到 f()接收63 int s。

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.

以下是完整的C ++ 17示例

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);
 }

在C ++ 14中有点复杂,因为没有可变参数使用,因此您必须以递归方式编写 foo 类。

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.

在C ++ 11中,您还必须开发 std :: make_index_sequence / std :: index_sequence

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

这篇关于有没有一种方法可以定义相同类型的各种参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆