c++中参数的可变数量?

时间:2021-07-02 23:15:46

How can I write a function that accepts a variable number of arguments? Is this possible, how?

如何编写一个函数来接受变量的参数?这是可能的,如何?

14 个解决方案

#1


111  

You probably shouldn't, and you can probably do what you want to do in a safer and simpler way. Technically to use variable number of arguments in C you include stdarg.h. From that you'll get the va_list type as well as three functions that operate on it called va_start(), va_arg() and va_end().

你可能不应该这样做,你也可以用一种更安全、更简单的方式来做你想做的事情。从技术上讲,在C中使用可变数量的参数,包括stdarg.h。从这里,您将获得va_list类型以及三个在其上操作的函数,称为va_start()、va_arg()和va_end()。

#include<stdarg.h>

int maxof(int n_args, ...)
{
    va_list ap;
    va_start(ap, n_args);
    int max = va_arg(ap, int);
    for(int i = 2; i <= n_args; i++) {
        int a = va_arg(ap, int);
        if(a > max) max = a;
    }
    va_end(ap);
    return max;
}

If you ask me, this is a mess. It looks bad, it's unsafe, and it's full of technical details that have nothing to do with what you're conceptually trying to achieve. Instead, consider using overloading or inheritance/polymorphism, builder pattern (as in operator<<() in streams) or default arguments etc. These are all safer: the compiler gets to know more about what you're trying to do so there are more occasions it can stop you before you blow your leg off.

如果你问我,这是一团糟。它看起来很糟糕,不安全,而且它充满了技术细节,与你在概念上试图达到的目标毫无关系。相反,考虑使用重载或继承/多态性、生成器模式(如流中的操作符<<())或默认参数等等。这些都更安全:编译器可以更了解你想要做什么,所以在你把你的腿放掉之前,有更多的机会可以阻止你。

#2


268  

In C++11 you have two new options, as the Variadic functions reference page in the Alternatives section states:

在c++ 11中,您有两个新选项,作为可选部分中的可变函数参考页面:

  • Variadic templates can also be used to create functions that take variable number of arguments. They are often the better choice because they do not impose restrictions on the types of the arguments, do not perform integral and floating-point promotions, and are type safe. (since C++11)
  • 可变模板还可以用于创建具有可变数量参数的函数。它们通常是更好的选择,因为它们不限制参数的类型,不执行积分和浮点提升,并且是类型安全的。(因为c++ 11)
  • If all variable arguments share a common type, a std::initializer_list provides a convenient mechanism (albeit with a different syntax) for accessing variable arguments.
  • 如果所有变量参数共享一个公共类型,那么std::initializer_list提供了一个方便的机制(尽管使用了不同的语法)来访问变量参数。

Below is an example showing both alternatives (see it live):

下面是一个展示两种选择的例子(参见live):

#include <iostream>
#include <string>
#include <initializer_list>

template <typename T>
void func(T t) 
{
    std::cout << t << std::endl ;
}

template<typename T, typename... Args>
void func(T t, Args... args) // recursive variadic function
{
    std::cout << t <<std::endl ;

    func(args...) ;
}

template <class T>
void func2( std::initializer_list<T> list )
{
    for( auto elem : list )
    {
        std::cout << elem << std::endl ;
    }
}

int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    func(1,2.5,'a',str1);

    func2( {10, 20, 30, 40 }) ;
    func2( {str1, str2 } ) ;
} 

If you are using gcc or clang we can use the PRETTY_FUNCTION magic variable to display the type signature of the function which can be helpful in understanding what is going on. For example using:

如果您使用的是gcc或clang,我们可以使用PRETTY_FUNCTION magic变量来显示函数的类型签名,这有助于理解正在发生的事情。例如使用:

std::cout << __PRETTY_FUNCTION__ << ": " << t <<std::endl ;

would results int following for variadic functions in the example (see it live):

在这个例子中(见它的live)中,将会产生以下变量:

void func(T, Args...) [T = int, Args = <double, char, std::basic_string<char>>]: 1
void func(T, Args...) [T = double, Args = <char, std::basic_string<char>>]: 2.5
void func(T, Args...) [T = char, Args = <std::basic_string<char>>]: a
void func(T) [T = std::basic_string<char>]: Hello

In Visual Studio you can use FUNCSIG.

在Visual Studio中,您可以使用FUNCSIG。

Update Pre C++11

更新之前的c++ 11

Pre C++11 the alternative for std::initializer_list would be std::vector or one of the other standard containers:

prec++ 11替代std::initializer_list将是std::vector或其他标准容器:

#include <iostream>
#include <string>
#include <vector>

template <class T>
void func1( std::vector<T> vec )
{
    for( typename std::vector<T>::iterator iter = vec.begin();  iter != vec.end(); ++iter )
    {
        std::cout << *iter << std::endl ;
    }
}

int main()
{
    int arr1[] = {10, 20, 30, 40} ;
    std::string arr2[] = { "hello", "world" } ; 
    std::vector<int> v1( arr1, arr1+4 ) ;
    std::vector<std::string> v2( arr2, arr2+2 ) ;

    func1( v1 ) ;
    func1( v2 ) ;
}

and the alternative for variadic templates would be variadic functions although they are not type-safe and in general error prone and can be unsafe to use but the only other potential alternative would be to use default arguments, although that has limited use. The example below is a modified version of the sample code in the linked reference:

可变模板的另一种选择是可变的函数,尽管它们不是类型安全的,而且通常容易出错,而且可能不安全,但是唯一的另一种可能的替代方法是使用默认参数,尽管它的使用有限。下面的示例是链接引用中示例代码的修改版本:

#include <iostream>
#include <string>
#include <cstdarg>

void simple_printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            std::cout << i << '\n';
        } else if (*fmt == 's') {
            char * s = va_arg(args, char*);
            std::cout << s << '\n';
        }
        ++fmt;
    }

    va_end(args);
}


int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    simple_printf("dddd", 10, 20, 30, 40 );
    simple_printf("ss", str1.c_str(), str2.c_str() ); 

    return 0 ;
} 

Using variadic functions also comes with restrictions in the arguments you can pass which is detailed in the draft C++ standard in section 5.2.2 Function call paragraph 7:

使用可变的函数还会有一些参数的限制,你可以通过在第5.2.2节函数调用第7段中的c++标准草案中详细说明。

When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.7). The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed. If the argument has a non-POD class type (clause 9), the behavior is undefined. [...]

当给定参数没有参数时,通过调用va_arg(18.7)来传递参数,这样接收函数就可以获得参数的值。在参数表达式上执行lvalue-to-rvalue(4.1)、arrayto -pointer(4.2)和functionto -pointer(4.3)标准转换。在这些转换之后,如果该参数没有算术、枚举、指针、指向成员的指针或类类型,则该程序是不正确的。如果该参数有一个非pod类类型(第9条),则该行为是未定义的。[…]

#3


16  

C-style variadic functions are supported in C++.

c++中支持C风格的变量函数。

However, most C++ libraries use an alternative idiom e.g. whereas the 'c' printf function takes variable arguments the c++ cout object uses << overloading which addresses type safety and ADTs (perhaps at the cost of implementation simplicity).

然而,大多数c++库使用了一个替代的习惯用法,例如,“C”printf函数采用变量参数,c++ cout对象使用< <重载,以处理类型安全和adt(可能是为了实现简单性的代价)。< p>

#4


14  

In C++11 there is a way to do variable argument templates which lead to a really elegant and type safe way to have variable argument functions. Bjarne himself gives a nice example of printf using variable argument templates in the C++11FAQ.

在c++ 11中,有一种方法可以使用变量参数模板,这将导致一个非常优雅和类型安全的方法来使用变量参数函数。Bjarne自己在c++ 11FAQ中使用变量参数模板给printf提供了一个很好的例子。

Personally, I consider this so elegant that I wouldn't even bother with a variable argument function in C++ until that compiler has support for C++11 variable argument templates.

就我个人而言,我认为这是如此的优雅,以至于我甚至不会在c++中使用变量参数函数,直到该编译器支持c++ 11变量参数模板。

#5


13  

Apart from varargs or overloading, you could consider to aggregate your arguments in a std::vector or other containers (std::map for example). Something like this:

除了varargs或重载之外,您可以考虑将您的参数集中在std::vector或其他容器(std::map)。是这样的:

template <typename T> void f(std::vector<T> const&);
std::vector<int> my_args;
my_args.push_back(1);
my_args.push_back(2);
f(my_args);

In this way you would gain type safety and the logical meaning of these variadic arguments would be apparent.

通过这种方式,您将获得类型安全,这些变量参数的逻辑意义将是显而易见的。

Surely this approach can have performance issues but you should not worry about them unless you are sure that you cannot pay the price. It is a sort of a a "Pythonic" approach to c++ ...

当然,这种方法可能有性能问题,但您不应该担心它们,除非您确定您不能为此付出代价。这是对c++的一种“python”方法。

#6


9  

The only way is through the use of C style variable arguments, as described here. Note that this is not a recommended practice, as it's not typesafe and error-prone.

唯一的方法是通过使用C风格的变量参数,如这里所述。请注意,这不是推荐的做法,因为它不是类型错误和容易出错的。

#7


9  

There is no standard C++ way to do this without resorting to C-style varargs (...).

没有使用C风格的varargs(…),没有标准的c++方法。

There are of course default arguments that sort of "look" like variable number of arguments depending on the context:

当然也有默认的参数,类似于变量数量的参数取决于上下文:

void myfunc( int i = 0, int j = 1, int k = 2 );

// other code...

myfunc();
myfunc( 2 );
myfunc( 2, 1 );
myfunc( 2, 1, 0 );

All four function calls call myfunc with varying number of arguments. If none are given, the default arguments are used. Note however, that you can only omit trailing arguments. There is no way, for example to omit i and give only j.

所有四个函数都调用myfunc,参数数量不同。如果没有给出,则使用默认参数。但是请注意,您只能省略尾随参数。没有办法,例如省略i,只给出j。

#8


9  

in c++11 you can do:

在c++11中,你可以这样做:

void foo(const std::list<std::string> & myArguments) {
   //do whatever you want, with all the convenience of lists
}

foo({"arg1","arg2"});

list initializer FTW!

列表初始化增值!

#9


4  

It's possible you want overloading or default parameters - define the same function with defaulted parameters:

您可能想要重载或默认参数——使用默认参数定义相同的函数:

void doStuff( int a, double termstator = 1.0, bool useFlag = true )
{
   // stuff
}

void doStuff( double std_termstator )
{
   // assume the user always wants '1' for the a param
   return doStuff( 1, std_termstator );
}

This will allow you to call the method with one of four different calls:

这将允许您用四个不同的调用之一调用该方法:

doStuff( 1 );
doStuff( 2, 2.5 );
doStuff( 1, 1.0, false );
doStuff( 6.72 );

... or you could be looking for the v_args calling conventions from C.

…或者你也可以从C中寻找v_arg调用约定。

#10


2  

As others have said, C-style varargs. But you can also do something similar with default arguments.

就像其他人说的那样,c型的变速器。但是您也可以使用默认参数进行类似的操作。

#11


2  

If you know the range of number of arguments that will be provided, you can always use some function overloading, like

如果您知道将要提供的参数的范围,您可以使用一些函数重载,比如。

f(int a)
    {int res=a; return res;}
f(int a, int b)
    {int res=a+b; return res;}

and so on...

等等……

#12


1  

int fun(int n_args, ...) {
   int *p = &n_args; 
   int s = sizeof(int);
   p += s + s - 1;
   for(int i = 0; i < n_args; i++) {
     printf("A1 %d!\n", *p);
     p += 2;
   }
}

Plain version

普通的版本

#13


1  

Since the introduction of variadic templates in C++11 and fold expressions in C++17, it is possible to define a template-function which, at the callee site, is callable as if it was a varidic function but with the advantages to:

由于在c++ 11中引入了可变模板,并在c++ 17中对表达式进行了折叠,因此可以定义一个模板函数,在callee站点上,可以调用它,就像它是一个变量函数,但是它的优点是:

  • be strongly type safe;
  • 强类型安全;
  • work without the run-time information of the number of arguments, or without the usage of a "stop" argument.
  • 工作时没有参数数量的运行时信息,或者不使用“停止”参数。

Here is an example for mixed argument types

这里有一个混合参数类型的例子。

template<class... Args>
void print(Args... args)
{
    (std::cout << ... << args) << "\n";
}
print(1, ':', " Hello", ',', " ", "World!");

And another with enforced type match for all arguments:

另一种是强制类型匹配所有参数:

#include <type_traits> // enable_if, conjuction

template<class Head, class... Tail>
using are_same = std::conjunction<std::is_same<Head, Tail>...>;

template<class Head, class... Tail, class = std::enable_if_t<are_same<Head, Tail...>::value, void>>
void print_same_type(Head head, Tail... tail)
{
    std::cout << head;
    (std::cout << ... << tail) << "\n";
}
print_same_type("2: ", "Hello, ", "World!");   // OK
print_same_type(3, ": ", "Hello, ", "World!"); // no matching function for call to 'print_same_type(int, const char [3], const char [8], const char [7])'
                                                  print_same_type(3, ": ", "Hello, ", "World!");
                                                                                              ^

More information:

更多信息:

  1. Variadic templates, also known as parameter pack Parameter pack(since C++11) - cppreference.com.
  2. 变量模板,也称为参数包参数包(因为c++ 11) - cppreference.com。
  3. Fold expressions fold expression(since C++17) - cppreference.com.
  4. 折叠表达式折叠表达式(因为c++ 17) - cppreference.com。
  5. See a full program demonstration on coliru.
  6. 参见coliru上的完整程序演示。

#14


0  

We could also use an initializer_list if all arguments are const and of the same type

如果所有参数都是const和相同类型,我们也可以使用initializer_list。

#1


111  

You probably shouldn't, and you can probably do what you want to do in a safer and simpler way. Technically to use variable number of arguments in C you include stdarg.h. From that you'll get the va_list type as well as three functions that operate on it called va_start(), va_arg() and va_end().

你可能不应该这样做,你也可以用一种更安全、更简单的方式来做你想做的事情。从技术上讲,在C中使用可变数量的参数,包括stdarg.h。从这里,您将获得va_list类型以及三个在其上操作的函数,称为va_start()、va_arg()和va_end()。

#include<stdarg.h>

int maxof(int n_args, ...)
{
    va_list ap;
    va_start(ap, n_args);
    int max = va_arg(ap, int);
    for(int i = 2; i <= n_args; i++) {
        int a = va_arg(ap, int);
        if(a > max) max = a;
    }
    va_end(ap);
    return max;
}

If you ask me, this is a mess. It looks bad, it's unsafe, and it's full of technical details that have nothing to do with what you're conceptually trying to achieve. Instead, consider using overloading or inheritance/polymorphism, builder pattern (as in operator<<() in streams) or default arguments etc. These are all safer: the compiler gets to know more about what you're trying to do so there are more occasions it can stop you before you blow your leg off.

如果你问我,这是一团糟。它看起来很糟糕,不安全,而且它充满了技术细节,与你在概念上试图达到的目标毫无关系。相反,考虑使用重载或继承/多态性、生成器模式(如流中的操作符<<())或默认参数等等。这些都更安全:编译器可以更了解你想要做什么,所以在你把你的腿放掉之前,有更多的机会可以阻止你。

#2


268  

In C++11 you have two new options, as the Variadic functions reference page in the Alternatives section states:

在c++ 11中,您有两个新选项,作为可选部分中的可变函数参考页面:

  • Variadic templates can also be used to create functions that take variable number of arguments. They are often the better choice because they do not impose restrictions on the types of the arguments, do not perform integral and floating-point promotions, and are type safe. (since C++11)
  • 可变模板还可以用于创建具有可变数量参数的函数。它们通常是更好的选择,因为它们不限制参数的类型,不执行积分和浮点提升,并且是类型安全的。(因为c++ 11)
  • If all variable arguments share a common type, a std::initializer_list provides a convenient mechanism (albeit with a different syntax) for accessing variable arguments.
  • 如果所有变量参数共享一个公共类型,那么std::initializer_list提供了一个方便的机制(尽管使用了不同的语法)来访问变量参数。

Below is an example showing both alternatives (see it live):

下面是一个展示两种选择的例子(参见live):

#include <iostream>
#include <string>
#include <initializer_list>

template <typename T>
void func(T t) 
{
    std::cout << t << std::endl ;
}

template<typename T, typename... Args>
void func(T t, Args... args) // recursive variadic function
{
    std::cout << t <<std::endl ;

    func(args...) ;
}

template <class T>
void func2( std::initializer_list<T> list )
{
    for( auto elem : list )
    {
        std::cout << elem << std::endl ;
    }
}

int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    func(1,2.5,'a',str1);

    func2( {10, 20, 30, 40 }) ;
    func2( {str1, str2 } ) ;
} 

If you are using gcc or clang we can use the PRETTY_FUNCTION magic variable to display the type signature of the function which can be helpful in understanding what is going on. For example using:

如果您使用的是gcc或clang,我们可以使用PRETTY_FUNCTION magic变量来显示函数的类型签名,这有助于理解正在发生的事情。例如使用:

std::cout << __PRETTY_FUNCTION__ << ": " << t <<std::endl ;

would results int following for variadic functions in the example (see it live):

在这个例子中(见它的live)中,将会产生以下变量:

void func(T, Args...) [T = int, Args = <double, char, std::basic_string<char>>]: 1
void func(T, Args...) [T = double, Args = <char, std::basic_string<char>>]: 2.5
void func(T, Args...) [T = char, Args = <std::basic_string<char>>]: a
void func(T) [T = std::basic_string<char>]: Hello

In Visual Studio you can use FUNCSIG.

在Visual Studio中,您可以使用FUNCSIG。

Update Pre C++11

更新之前的c++ 11

Pre C++11 the alternative for std::initializer_list would be std::vector or one of the other standard containers:

prec++ 11替代std::initializer_list将是std::vector或其他标准容器:

#include <iostream>
#include <string>
#include <vector>

template <class T>
void func1( std::vector<T> vec )
{
    for( typename std::vector<T>::iterator iter = vec.begin();  iter != vec.end(); ++iter )
    {
        std::cout << *iter << std::endl ;
    }
}

int main()
{
    int arr1[] = {10, 20, 30, 40} ;
    std::string arr2[] = { "hello", "world" } ; 
    std::vector<int> v1( arr1, arr1+4 ) ;
    std::vector<std::string> v2( arr2, arr2+2 ) ;

    func1( v1 ) ;
    func1( v2 ) ;
}

and the alternative for variadic templates would be variadic functions although they are not type-safe and in general error prone and can be unsafe to use but the only other potential alternative would be to use default arguments, although that has limited use. The example below is a modified version of the sample code in the linked reference:

可变模板的另一种选择是可变的函数,尽管它们不是类型安全的,而且通常容易出错,而且可能不安全,但是唯一的另一种可能的替代方法是使用默认参数,尽管它的使用有限。下面的示例是链接引用中示例代码的修改版本:

#include <iostream>
#include <string>
#include <cstdarg>

void simple_printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);

    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            std::cout << i << '\n';
        } else if (*fmt == 's') {
            char * s = va_arg(args, char*);
            std::cout << s << '\n';
        }
        ++fmt;
    }

    va_end(args);
}


int main()
{
    std::string
        str1( "Hello" ),
        str2( "world" );

    simple_printf("dddd", 10, 20, 30, 40 );
    simple_printf("ss", str1.c_str(), str2.c_str() ); 

    return 0 ;
} 

Using variadic functions also comes with restrictions in the arguments you can pass which is detailed in the draft C++ standard in section 5.2.2 Function call paragraph 7:

使用可变的函数还会有一些参数的限制,你可以通过在第5.2.2节函数调用第7段中的c++标准草案中详细说明。

When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.7). The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed. If the argument has a non-POD class type (clause 9), the behavior is undefined. [...]

当给定参数没有参数时,通过调用va_arg(18.7)来传递参数,这样接收函数就可以获得参数的值。在参数表达式上执行lvalue-to-rvalue(4.1)、arrayto -pointer(4.2)和functionto -pointer(4.3)标准转换。在这些转换之后,如果该参数没有算术、枚举、指针、指向成员的指针或类类型,则该程序是不正确的。如果该参数有一个非pod类类型(第9条),则该行为是未定义的。[…]

#3


16  

C-style variadic functions are supported in C++.

c++中支持C风格的变量函数。

However, most C++ libraries use an alternative idiom e.g. whereas the 'c' printf function takes variable arguments the c++ cout object uses << overloading which addresses type safety and ADTs (perhaps at the cost of implementation simplicity).

然而,大多数c++库使用了一个替代的习惯用法,例如,“C”printf函数采用变量参数,c++ cout对象使用< <重载,以处理类型安全和adt(可能是为了实现简单性的代价)。< p>

#4


14  

In C++11 there is a way to do variable argument templates which lead to a really elegant and type safe way to have variable argument functions. Bjarne himself gives a nice example of printf using variable argument templates in the C++11FAQ.

在c++ 11中,有一种方法可以使用变量参数模板,这将导致一个非常优雅和类型安全的方法来使用变量参数函数。Bjarne自己在c++ 11FAQ中使用变量参数模板给printf提供了一个很好的例子。

Personally, I consider this so elegant that I wouldn't even bother with a variable argument function in C++ until that compiler has support for C++11 variable argument templates.

就我个人而言,我认为这是如此的优雅,以至于我甚至不会在c++中使用变量参数函数,直到该编译器支持c++ 11变量参数模板。

#5


13  

Apart from varargs or overloading, you could consider to aggregate your arguments in a std::vector or other containers (std::map for example). Something like this:

除了varargs或重载之外,您可以考虑将您的参数集中在std::vector或其他容器(std::map)。是这样的:

template <typename T> void f(std::vector<T> const&);
std::vector<int> my_args;
my_args.push_back(1);
my_args.push_back(2);
f(my_args);

In this way you would gain type safety and the logical meaning of these variadic arguments would be apparent.

通过这种方式,您将获得类型安全,这些变量参数的逻辑意义将是显而易见的。

Surely this approach can have performance issues but you should not worry about them unless you are sure that you cannot pay the price. It is a sort of a a "Pythonic" approach to c++ ...

当然,这种方法可能有性能问题,但您不应该担心它们,除非您确定您不能为此付出代价。这是对c++的一种“python”方法。

#6


9  

The only way is through the use of C style variable arguments, as described here. Note that this is not a recommended practice, as it's not typesafe and error-prone.

唯一的方法是通过使用C风格的变量参数,如这里所述。请注意,这不是推荐的做法,因为它不是类型错误和容易出错的。

#7


9  

There is no standard C++ way to do this without resorting to C-style varargs (...).

没有使用C风格的varargs(…),没有标准的c++方法。

There are of course default arguments that sort of "look" like variable number of arguments depending on the context:

当然也有默认的参数,类似于变量数量的参数取决于上下文:

void myfunc( int i = 0, int j = 1, int k = 2 );

// other code...

myfunc();
myfunc( 2 );
myfunc( 2, 1 );
myfunc( 2, 1, 0 );

All four function calls call myfunc with varying number of arguments. If none are given, the default arguments are used. Note however, that you can only omit trailing arguments. There is no way, for example to omit i and give only j.

所有四个函数都调用myfunc,参数数量不同。如果没有给出,则使用默认参数。但是请注意,您只能省略尾随参数。没有办法,例如省略i,只给出j。

#8


9  

in c++11 you can do:

在c++11中,你可以这样做:

void foo(const std::list<std::string> & myArguments) {
   //do whatever you want, with all the convenience of lists
}

foo({"arg1","arg2"});

list initializer FTW!

列表初始化增值!

#9


4  

It's possible you want overloading or default parameters - define the same function with defaulted parameters:

您可能想要重载或默认参数——使用默认参数定义相同的函数:

void doStuff( int a, double termstator = 1.0, bool useFlag = true )
{
   // stuff
}

void doStuff( double std_termstator )
{
   // assume the user always wants '1' for the a param
   return doStuff( 1, std_termstator );
}

This will allow you to call the method with one of four different calls:

这将允许您用四个不同的调用之一调用该方法:

doStuff( 1 );
doStuff( 2, 2.5 );
doStuff( 1, 1.0, false );
doStuff( 6.72 );

... or you could be looking for the v_args calling conventions from C.

…或者你也可以从C中寻找v_arg调用约定。

#10


2  

As others have said, C-style varargs. But you can also do something similar with default arguments.

就像其他人说的那样,c型的变速器。但是您也可以使用默认参数进行类似的操作。

#11


2  

If you know the range of number of arguments that will be provided, you can always use some function overloading, like

如果您知道将要提供的参数的范围,您可以使用一些函数重载,比如。

f(int a)
    {int res=a; return res;}
f(int a, int b)
    {int res=a+b; return res;}

and so on...

等等……

#12


1  

int fun(int n_args, ...) {
   int *p = &n_args; 
   int s = sizeof(int);
   p += s + s - 1;
   for(int i = 0; i < n_args; i++) {
     printf("A1 %d!\n", *p);
     p += 2;
   }
}

Plain version

普通的版本

#13


1  

Since the introduction of variadic templates in C++11 and fold expressions in C++17, it is possible to define a template-function which, at the callee site, is callable as if it was a varidic function but with the advantages to:

由于在c++ 11中引入了可变模板,并在c++ 17中对表达式进行了折叠,因此可以定义一个模板函数,在callee站点上,可以调用它,就像它是一个变量函数,但是它的优点是:

  • be strongly type safe;
  • 强类型安全;
  • work without the run-time information of the number of arguments, or without the usage of a "stop" argument.
  • 工作时没有参数数量的运行时信息,或者不使用“停止”参数。

Here is an example for mixed argument types

这里有一个混合参数类型的例子。

template<class... Args>
void print(Args... args)
{
    (std::cout << ... << args) << "\n";
}
print(1, ':', " Hello", ',', " ", "World!");

And another with enforced type match for all arguments:

另一种是强制类型匹配所有参数:

#include <type_traits> // enable_if, conjuction

template<class Head, class... Tail>
using are_same = std::conjunction<std::is_same<Head, Tail>...>;

template<class Head, class... Tail, class = std::enable_if_t<are_same<Head, Tail...>::value, void>>
void print_same_type(Head head, Tail... tail)
{
    std::cout << head;
    (std::cout << ... << tail) << "\n";
}
print_same_type("2: ", "Hello, ", "World!");   // OK
print_same_type(3, ": ", "Hello, ", "World!"); // no matching function for call to 'print_same_type(int, const char [3], const char [8], const char [7])'
                                                  print_same_type(3, ": ", "Hello, ", "World!");
                                                                                              ^

More information:

更多信息:

  1. Variadic templates, also known as parameter pack Parameter pack(since C++11) - cppreference.com.
  2. 变量模板,也称为参数包参数包(因为c++ 11) - cppreference.com。
  3. Fold expressions fold expression(since C++17) - cppreference.com.
  4. 折叠表达式折叠表达式(因为c++ 17) - cppreference.com。
  5. See a full program demonstration on coliru.
  6. 参见coliru上的完整程序演示。

#14


0  

We could also use an initializer_list if all arguments are const and of the same type

如果所有参数都是const和相同类型,我们也可以使用initializer_list。