C++ C++;如何在没有前面参数的情况下使用省略号

C++ C++;如何在没有前面参数的情况下使用省略号,c++,variadic-functions,C++,Variadic Functions,嗨 我有一个类,它有一个成员函数,该函数接受数量可变的参数。类知道实例化后需要多少个参数。e、 g 在我看来,必须不断地指定我传递的参数的数量是不整洁的。最好的办法是什么?我考虑过重载一组函数,每个函数都有n个参数,一个宏来为我放入num_参数。但理想情况下,我希望能够将“做某事”定义为 void do_something(...); 以某种方式让stdargs的东西与类的num_参数一起工作,而不是传递一个值 非常感谢您的想法。我不明白您为什么不能在函数本身中使用na,即 void myCl

嗨 我有一个类,它有一个成员函数,该函数接受数量可变的参数。类知道实例化后需要多少个参数。e、 g

在我看来,必须不断地指定我传递的参数的数量是不整洁的。最好的办法是什么?我考虑过重载一组函数,每个函数都有n个参数,一个宏来为我放入num_参数。但理想情况下,我希望能够将“做某事”定义为

void do_something(...);
以某种方式让stdargs的东西与类的num_参数一起工作,而不是传递一个值


非常感谢您的想法。

我不明白您为什么不能在函数本身中使用
na
,即

void myClass::do_something(int num_args, ...)
{
 va_list vl;
 va_start(vl, na);
 for(int i=0; i < na; i++)
   do_anotherthing(va_arg(vl, type));
 va_end
}
其中,
运算符%
对提供的每个元素执行另一项操作,直到达到最大值

Edit:进一步考虑后,最好是
dou\u something
返回一个helper对象,该对象为其执行所有操作,例如

do_something_helper myClass::do_something() { 
  return do_something_helper( na ); }

struct do_something_helper {
  int count;
  do_something_helper( int c ) : count( c ) {}

  template< class T >
  do_something_helper& operator%( T val ) {
     --count;
     if ( count < 0 ) {
      //trigger some error condition
     }
     do_anotherthing( val );
     return *this;
  }

  ~do_something_helper() {
    if ( count > 0 ) { // too few args
      //trigger some error condition
    }
  }
}
最好的办法是什么

<>你可以考虑使用一个前哨值,这样你就不必对这些元素进行计数了——它更少(但仍然)容易出错。从使用安全的角度来看,重载可能更好,但显然,如果参数的数量经常很大且不可预测,那么重载就变得不切实际了

更好的方法是传入
向量
或数组。使用数组,可以让被调用函数知道大小:

template <size_t N>
void f(type (&x)[N])
{
    ...
}
模板
无效f(类型(&x)[N])
{
...
}

您的示例表明
类型
是常量,并且在编译时已知,因此
向量
或数组就足够了。如果这是一个简化,考虑一个<代码>向量>代码>或Boox<代码>变体> <代码>或<代码> < < />代码>,或者也许是<代码> tuple < /代码>,或者是一个返回对象引用的函数,以便您可以提供连续值的链式调用(许多操作员这样做)。参数数目可变在C语言中非常少见++

实现所需的最佳方法是创建一个int列表并将该列表作为参数传递


您可以检查函数中列表的大小,而不是使用varargs。您可以使用
运算符吗?我知道这不是一个好的做法,有更好的解决方案来解决这个问题,但作为省略号参数的做法,我发现这是一个很好的练习

这段代码适用于我的编译器(VS2013),很抱歉我不得不使用内联汇编,但由于堆栈组织的原因,使用局部堆栈变量的第一个想法无法工作。 这就是:

#include <iostream>
#include <cstdarg>
#include <stdint.h>

using namespace std;

double avg(double * sp, ...);

#define AVERAGE(n, ...)                         \
{                                               \
    int * stackP;                               \
    __asm {                                     \
        __asm mov ebx, esp                      \
        __asm mov stackP, ebx                   \
    }                                           \
    double a = avg(stackP, n, __VA_ARGS__);     \
    cout << "Average is: " << a << endl;        \
}

template <typename T>
double avg(int * sp, T n, ...)
{
    va_list list;
    va_start(list, n);
    double result = n;
    unsigned int count = 1;
    T * pArg = 0;

    while (sp > reinterpret_cast<int *>(pArg + 1))
    {
        pArg = &(va_arg(list, T));
        result += *pArg;
        count++;
    }

    va_end(list);

    result /= count;
    return result;
}

void main()
{
    AVERAGE(1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6);
    AVERAGE(1.2, 1.3, 1.4, 1.5, 1.6);
    AVERAGE(1.2, 1.3, 1.4);
    AVERAGE(2, 3, 4);
    AVERAGE(2, 3, 4, 5, 6);
}
#包括
#包括
#包括
使用名称空间std;
双平均值(双*sp,…);
#定义平均值(n,…)\
{                                               \
int*stackP\
__asm{\
__电除尘器\
__asm mov stackP,ebx\
}                                           \
双a=平均值(叠加P,n,V参数)\

看起来C++0X的可变模板很适合这里,但我不太了解它们,也不知道编译器在这一点上支持它们什么。(g++可能会这样做)@乔:你打电话来了,先生?我认为它不常见的主要原因是它很难做到并且仍然是类型安全的。随着C++0x变得越来越流行和越来越广泛的支持,它会变得越来越普遍。只要printf()(和它的50个兄弟)就实现而言,我们需要记住应用程序。简单地将N个参数推到堆栈上并牺牲一些类型安全性,而不是创建多态对象列表(他从未说过所有参数都是int),计算成本要低得多。
do_something_helper myClass::do_something() { 
  return do_something_helper( na ); }

struct do_something_helper {
  int count;
  do_something_helper( int c ) : count( c ) {}

  template< class T >
  do_something_helper& operator%( T val ) {
     --count;
     if ( count < 0 ) {
      //trigger some error condition
     }
     do_anotherthing( val );
     return *this;
  }

  ~do_something_helper() {
    if ( count > 0 ) { // too few args
      //trigger some error condition
    }
  }
}
A.do_something() % a % b % c % d % e;
template <size_t N>
void f(type (&x)[N])
{
    ...
}
#include <iostream>
#include <cstdarg>
#include <stdint.h>

using namespace std;

double avg(double * sp, ...);

#define AVERAGE(n, ...)                         \
{                                               \
    int * stackP;                               \
    __asm {                                     \
        __asm mov ebx, esp                      \
        __asm mov stackP, ebx                   \
    }                                           \
    double a = avg(stackP, n, __VA_ARGS__);     \
    cout << "Average is: " << a << endl;        \
}

template <typename T>
double avg(int * sp, T n, ...)
{
    va_list list;
    va_start(list, n);
    double result = n;
    unsigned int count = 1;
    T * pArg = 0;

    while (sp > reinterpret_cast<int *>(pArg + 1))
    {
        pArg = &(va_arg(list, T));
        result += *pArg;
        count++;
    }

    va_end(list);

    result /= count;
    return result;
}

void main()
{
    AVERAGE(1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6);
    AVERAGE(1.2, 1.3, 1.4, 1.5, 1.6);
    AVERAGE(1.2, 1.3, 1.4);
    AVERAGE(2, 3, 4);
    AVERAGE(2, 3, 4, 5, 6);
}