[vc++] как скопировать список аргументов функции?

marizha

вот чего я хочу, используя <stdarg.h>:


class a
{
public:
void SetArg(int , ...);
private:
void func;
arg_list Arg;
};
void SetArg(int a, ... )
{
va_list argptr;
va_start(argptr, a);
//?Arg va_copy, описанный в справочнике Г.Шилдта, почему-то отсутсвует... как скопировать список аргументов :( ?
}
void a::func
{
SomeFunc(Arg);
}


при создании класса я бы хотел передать список аргументов через SetArg(...);
а далее использовать его в НЕ виртуальной функции... т.к. мне нужен массив объектов этого класса, но с разными аргументами для функции...

rosali

Пара вопросов для прояснения ситуации:
1) Что такое int a (первый аргумент в твоем SetArg)?
2) Что такое arg_list?
PS.

int never_call_me(void *, ... );


marizha

почитай об этом в msdn... (va_arg, va_start, va_end)
и если узнаешь, как сохранить список аргументов, переданных функции, плз. сообщи :P

Dasar

параметры имеют один тип или разный?

rosali

почитай об этом в msdn

Я перед тем как написать между прочим как раз посмотрел в MSDN, а ты?
Никакого arg_list там нет, а что ты хочешь про int a в MSDN увидеть я вообще не понял...

Dasar

В MS VC вместо arg_list используется va_list:
va_list structure
Used to hold information needed by va_arg and va_end macros. Called function declares variable of type va_list that can be passed as argument to another function.
STDARG.H,
CRTDEFS.H

rosali

Ясно, спасибо. Тогда новые вопросы :
1) Я правильно понимаю, что этот va_list - это просто указатель в стек? Какой тогда смысл хранить его в поле объекта, стек то уплывет?..
2) А как узнавать сколько передано аргументов? Тот же printf узнает о количестве и типах аргументов по строке-формату, а тут? Этот самый int a?

Dasar

Access variable-argument lists.

type va_arg(
va_list arg_ptr,
type
);
void va_end(
va_list arg_ptr
);
void va_start(
va_list arg_ptr
); // (UNIX version)
void va_start(
va_list arg_ptr,
prev_param
); // (ANSI version)

Parameters
type
Type of argument to be retrieved.
arg_ptr
Pointer to list of arguments.
prev_param
Parameter preceding first optional argument (ANSI only).
Return Value
va_arg returns the current argument; va_start and va_end do not return values.
Remarks
The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are:
va_alist
Name of parameter to called function (UNIX version only)
va_arg
Macro to retrieve current argument
va_dcl
Declaration of va_alist (UNIX version only)
va_end
Macro to reset arg_ptr
va_list
typedef for pointer to list of arguments defined in STDIO.H
va_start
Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only)
Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed.
The ANSI C standard macros, defined in STDARG.H, are used as follows:
All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros.
va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro's behavior is undefined. va_start must be used before va_arg is used for the first time.
va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.
After all arguments have been retrieved, va_end resets the pointer to NULL.
The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:
Any required arguments to the function can be declared as parameters in the usual way.
The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).
va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.
Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.
va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.
After all arguments have been retrieved, va_end resets the pointer to NULL.
Example
Copy Code
// crt_va.c
/* The program below illustrates passing a variable
* number of arguments using the following macros:
* va_start va_arg va_end
* va_list va_dcl (UNIX only)
*/
#include <stdio.h>
#define ANSI /* Comment out for UNIX version */
#ifdef ANSI /* ANSI compatible version */
#include <stdarg.h>
int average( int first, ... );
#else /* UNIX compatible version */
#include <varargs.h>
int average( va_list );
#endif
int main( void )
{
/* Call with 3 integers (-1 is used as terminator). */
printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );
/* Call with 4 integers. */
printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );
/* Call with just -1 terminator. */
printf( "Average is: %d\n", average( -1 ) );
}
/* Returns the average of a variable list of integers. */
#ifdef ANSI /* ANSI compatible version */
int average( int first, ... )
{
int count = 0, sum = 0, i = first;
va_list marker;
va_start( marker, first ); /* Initialize variable arguments. */
while( i != -1 )
{
sum += i;
count++;
i = va_arg( marker, int);
}
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#else /* UNIX compatible version must use old-style definition. */
int average( va_alist )
va_dcl
{
int i, count, sum;
va_list marker;
va_start( marker ); /* Initialize variable arguments. */
for( sum = count = 0; (i = va_arg( marker, int != -1; count++ )
sum += i;
va_end( marker ); /* Reset variable arguments. */
return( sum ? (sum / count) : 0 );
}
#endif

.NET Framework Equivalent
System::ParamArrayAttribute Class
Requirements
Routine
Required header
Optional headers
Compatibility

va_arg
<stdio.h> and <stdarg.h>
<varargs.h>*
ANSI, Windows 98, Windows Me, Windows NT, Windows 2000, Windows XP, Windows Server 2003

va_end
<stdio.h> and <stdarg.h>
<varargs.h>*
ANSI, Windows 98, Windows Me, Windows NT, Windows 2000, Windows XP, Windows Server 2003

va_start
<stdio.h> and <stdarg.h>
<varargs.h>*
ANSI, Windows 98, Windows Me, Windows NT, Windows 2000, Windows XP, Windows Server 2003

* Required for UNIX V compatibility.
For additional compatibility information, see Compatibility in the Introduction.
Libraries
All versions of the C run-time libraries.
Output
Copy Code
Average is: 3
Average is: 8
Average is: 0

marizha

ну так как сохранить (скопировать) этот va_list, чтобы далее возможно было передать его другой функции?

Dasar

Ты так и не ответил на вопрос:
параметры имеют один тип или разный?

marizha

произвольный, заранее не известный :|
но даже если известный, как бы это мне помогло? я смог бы их считать с помощью va_start и va_arg, а как их передать? как из них сделать опять va_list?

Dasar

Т.е. возможен вариант, когда один параметр -int, второй - bool, третий - string?

mirt1971

Третий стринг быть не может вообще. Через троеточие разрешено передавать лишь POD типы.

Dasar

пусть будет char * вместо string.

marizha

а что такое
POD типы
т.е. через ... можно передавать какое-то конечное множество типов?

mirt1971

Plain Old Data. Те никаких классов с нетривиальными конструкторами/деструкторами(вроде так)

rosali

какое-то конечное множество

Ну, заведомо бесконечное, можно передавать int, int* int**, int***,...
Кстати, может пора сформулировать какая _в итоге_ задача решается, не сомневаюсь, что удастся обойтись без этого долбаного "..." ? Это мне последний пост в FAQ навеял

marizha

мне нужен класс фильтров, обрабатывающий рисунки ... так вот я хочу унифицировать эти фильтры, для чего использую попросту указатель на функцию, передаваемый при инициализации... (например фильтру "акврель" я передаю указаель на фунцкию сортировки). конечно, можно унифицировать и передаваемые этим "указателям" параметры, но мне захотелось сделать более общий вид..
да и к тому же, теперь меня больше итересует не этот класс, а вообще возможность перепеси параметров функции и возможности динамического создания функций... но увы на это нет сейчас времени... сссесссия :P

rosali

можно унифицировать и передаваемые этим "указателям" параметры

по-моему не можно, а нужно, иначе будет у тебя от излишней всеощности тот самый never_call_me(...);
А вообще можно поподробнее в чем состоит унификация? Если есть абстрактный класс "фильтр", то ему просто надо придумать вуртуальную функцию "фильтровать", а при чем тут сортировка непонятно...
вообще возможность перепеси параметров функции

Я как-то недогоняю что это значит...
возможности динамического создания функций

Динамически надо создавать не функции, а экземпляры полиморфного класса. Это проще и общее...

marizha

просто мне не хотелось создавать для каждого фильтра свой класс... хотя, в принципе, так всегда и поступают
--------------------------------------------------------------------------------
вообще возможность перепеси параметров функции
--------------------------------------------------------------------------------
Я как-то недогоняю что это значит...

чего тут непонятного? я передаю некоторой функции параметры, а она их каким-либо образом сохраняет так, чтобы где-либо (в том числе и вне блока функции) можно было передать их некоторой другой функции
Оставить комментарий
Имя или ник:
Комментарий: