1

Is it possible to transfer list of parameters of a function , to another function?

For example in my functionA I want to call my functionB/functionC (depends on the state of execution) with the parameters from the varargs list. Please note, i cannot change functionB/functionC declaration.

int functionA(int a, ...){
    ...
    va_list listPointer;
    va_start( listPointer, a);
    ...
}

int functionB(long b, long c, long d){
    ...
    ...
}

int functionC(long b, int c, int d){
    ...
    ...
}

For this project I use gcc 4.9.1.

What i have tried till now is to pass the void* from the listPointer but it did not work...

Extracting variables from the va_list also will not work because i have like 80 other similair functions which should be called from the functionA , meaning i cannot extract parameters and call by extracted values.

Maybe there is a way to copy memory of the functionA parameters and call functionB/functionC with a pointer to it? Does anyone have an idea of how it would be possible?

Aksim Elnik
  • 425
  • 6
  • 27
  • read them out from `va_list listPointer` in function `functionA`, and pass them by value to `functionB` then. Or is that for some reason not intended? – Stephan Lechner May 15 '17 at 09:45
  • @StephanLechner Yes there is the reason, that, depending on the logic, my functionA may also call other functions that have different parameter types... Thats why extracting parameters explicitly won't work... I will add that to my question – Aksim Elnik May 15 '17 at 09:53
  • Possible duplicate of [Forward an invocation of a variadic function in C](http://stackoverflow.com/questions/150543/forward-an-invocation-of-a-variadic-function-in-c) – Lanting May 15 '17 at 09:53
  • Easy if you want to use variadic templates instead of C-style variadic function .. – M.M May 15 '17 at 10:02
  • @M.M Sorry, I am not that good in c++... Can you maybe give me some more information on this approach, or even a simple example? – Aksim Elnik May 15 '17 at 10:04

3 Answers3

2

If you cannot change your functionB, then you have to extract arguments from your functionA va list:

#include <stdarg.h>
#include <stdio.h>

int functionB(long b, long c, long d)
{
    return printf("b: %d, c: %d, d: %d\n", b, c, d);
}

int functionA(int a, ...)
{
    ...
    va_list va;
    va_start(va, a);
    long b = va_arg(va, long);
    long c = va_arg(va, long);
    long d = va_arg(va, long);
    va_end(va);
    return functionB(b, c, d);
}

Maybe there is a way to copy memory of the functionA parameters and call functionB/functionC with a pointer to it? Does anyone have an idea of how it would be possible?

Then it means that you would have to change declaration of your functionB, functionC etc. You might as well then change them to accept va_list instead:

int functionA(int a, va_list args);
int functionC(int c, va_list args);
Pavel P
  • 15,789
  • 11
  • 79
  • 128
  • Thank you for your proposal, but it won't work for my case, since I have a functionC which takes different parameters too... – Aksim Elnik May 15 '17 at 09:59
2

You can't change the signature of B, but can you change the one of A? If so, this might be a good option:

template <typename... Args>
int functionA(Args&& ... args)
{
    return functionB(std::forward<Args>(args)...);
}
Sebastian Stern
  • 632
  • 4
  • 15
  • Is it guaranteed then that only the 2nd up to the 4th argument of `functionA` is passed to `functionB`? – Stephan Lechner May 15 '17 at 09:53
  • @StephanLechner I think it is implied in the question that the caller would pass the right number and types of arguments for the selected function. Otherwise it is impossible to answer anyway – M.M May 15 '17 at 10:03
  • In this case no. But if the signature is changed to ``int functionA(int a, Args&& ... args)`` then yes. However the parameter ``a`` could be omitted, because I guess it's only used in the OP version to determine how many variadic arguments are supplied. Which in this case can be calculated using ``size_t v = sizeof(args...)`` – Sebastian Stern May 15 '17 at 10:06
  • M.M is right , that the right number and types are passed for the selected functions. However my compiler does not have std::forward ... – Aksim Elnik May 15 '17 at 10:09
  • @AksimElnik You should include your compiler name and version in the question then – M.M May 15 '17 at 10:10
  • gcc 4.9.1 has std::forward (use compile switch `-std=c++11` and `#include` the right header – M.M May 15 '17 at 10:16
  • @M.M according to ( http://en.cppreference.com/w/cpp/utility/forward ) , the forward is defined in the header... however when i include it , forward still cannot be resolved... – Aksim Elnik May 15 '17 at 10:33
  • Are you using `-std=c++11` switch? (and not any other switch). Anyway you should sort this issue out separately instead of in comments here – M.M May 15 '17 at 10:38
  • @M.M you were right, now i have resolved those issues... Now, in order to use this variadic template, i would need to instantiate that... Do you know howto do that with variadic arguments? – Aksim Elnik May 15 '17 at 12:19
  • @AksimElnik this answer shows how. Or you can google "perfect forwarding" for more detail – M.M May 15 '17 at 21:57
1

If you have only longs in your va_args that can work.

int functionA(int a, ...){
    va_list listPointer;
    va_start( listPointer, a);
    long b = va_arg(listPointer, long);
    long c = va_arg(listPointer, long);
    long d = va_arg(listPointer, long);
    va_end(listPointer);
    return functionB(b, c, d);
}
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Thank you for your proposal, but it won't work for my case, since I have a functionC which takes different parameters too... – Aksim Elnik May 15 '17 at 09:58