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