Calling a variadic function with an unknown number of parameters - c++

Say I have a function that takes a variable number of parameters: I want to call this function from somewhere else, building the list of parameters, but without knowing in advance how many parameters I'll need.
Sorry that's not well explained, hopefully this code makes my question clearer:
void foo(int n, ...) {
va_list vl;
va_start(vl,n);
for (int i = 0; i<n; i++) {
// Do something to each passed variable
}
}
That function's being called from this one:
void bar(int howManyParams) {
// Here I want to call foo() with howManyParams parameters
// (values are irrelevant for the question)
//
// I.e. for howManyParams = 1, we should call foo(0)
// for howManyParams = 2, we should call foo(0,0)
// for howManyParams = 3, we should call foo(0,0,0)
// etc.
//
}

Actually building a variable-length argument list at run-time -- which is what I'm pretty sure you're trying to do -- is pretty tricky. There's no way to do it at all in Standard C, but there are various tricks you can try.
Perhaps the best is the "Foreign Function Interface Library" at http://sourceware.org/libffi/ .
See also question 15.13 in the C FAQ list: http://c-faq.com/varargs/invvarargs.html
See also these previous Stackoverflow questions:
C late binding with unknown arguments
How to call functions by their pointers passing multiple arguments in C?

You will need a terminating parameter, it may be NULL, or something else, that should never appear in your real arguments. Inside your function you can loop over the arguments until you reach a terminating NULL or any other value you choose to signal the end.

If a special value cannot be reserved to indicate the end of the list, pass 2 arguments for each parameter. Tad wasteful but does allow code to be sequentially automatically generated without value restrictions.
foo(0);
foo(1, Params1, 0);
foo(1, Params1, 1, Params2, 0);
foo(1, Params1, 1, Params2, 1, Params3, 0);

The easier way to do at runtime what the OP asked is probably by relying on standard containers like std::vectors and the others.
Anyway, for the sake of completeness, here is an example of how a variadic pack of parameters can be created at compile time and used later to invoke a function:
#include<utility>
#include<tuple>
#include<iostream>
auto params(std::index_sequence<0>) {
return std::tuple<std::size_t>{};
}
template<std::size_t I, std::size_t... O>
auto params(std::index_sequence<I, O...>) {
auto tup = std::tuple<std::size_t>{ sizeof...(O) };
auto seq = std::make_index_sequence<sizeof...(O)>{};
return std::tuple_cat(tup, params(seq));
}
void foo() {
std::cout << "done." << std::endl;
}
template<typename Arg, typename... Args>
void foo(Arg &&arg, Args&&... args) {
std::cout << "arg: " << arg << ", still to be elaborated: " << sizeof...(Args) << std::endl;
foo(std::forward<Args>(args)...);
}
template<typename... Args, std::size_t... Indexes>
void invoke(std::tuple<Args...> &tup, std::index_sequence<Indexes...>) {
foo(std::get<Indexes>(tup)...);
}
template<std::size_t N>
void bar(std::integral_constant<std::size_t, N> size) {
auto seq = std::make_index_sequence<N>{};
auto tup = params(seq);
invoke(tup, seq);
}
int main() {
bar(std::integral_constant<std::size_t, 3>{});
bar(std::integral_constant<std::size_t, 5>{});
}
Unfortunately, for it must be completely resolved at compile time, the argument for the bar function cannot be a std::size_t for itself.
Instead, a std::integral_constant can be used to do that.

When I've need to do something like this, I got it to work with a "switch-fan".
switch( n ){
case 1: foo(0); break;
case 2: foo(0,0); break;
case 3: foo(0,0,0); break;
}

Related

Generate argument names from list of types to forward to another function

I would like to generate a function that forwards its arguments to another function. I know that std::function does it somehow, but I cannot seem to find the right syntax myself.
It would be ok for my usecase to use som kind of template magic, but i want
the user to be able to get information on the calling types when they use the function, like std::function does.
My usecase uses class member functions, so a solution that only works in that context is accepted. I tried to created the smallest example code possible.
#include <iostream>
// Macro usage cannot be changed
#define ARGS int, int
void otherFunction(int x, int y) {
std::cout << x << "," << y << "\n";
}
// This is the behaviour i want
void expectedImplementation(int _1, int _2) {
otherFunction(_1, _2);
}
// This works, but it prevents the user to view the expected
// types in their IDE
template <typename ...Args>
void templateVersion(Args ... args) {
otherFunction(args...);
}
// This is the version I cannot get to work
// It does not need to look like this, but it needs to get
// its argument types from
//void func(ARGS) {
// otherFunction(/*how?*/);
//}
int main() {
expectedImplementation(1, 2);
templateVersion(1, 2);
//func(1, 2);
}
godbolt
How do I accomplish this?
Edit:
The function that needs to be forwarded to is also different for each instance of the function.
Edit 2:
Ok, It seems like it's hard to specify the context without the context. Here is the actual code that I want to generalize. Here Is the template magick stuff where it should fit in. No memory should be used, otherwise I would just use the solution I have now with template parameter packs.
Edit 3:
A better example:
#include <iostream>
#define ARGS int, int
struct Inner {
void otherFunction(int x, int y) {
std::cout << x << y << std::endl;
}
};
struct Wrapper {
Inner inner;
// This works, but it prevents the user to view the expected
// types in their ide
template <typename ...Args>
void templateVersion(Args ... args) {
inner.otherFunction(args...);
}
// The concept I try to figure out
void function(ARGS) { // It does not need to look exactly like this
// , but functionally it needs to be somithing like it
// Forward the arguments to the `ìnner` class
}
};
int main() {
auto wrapper = Wrapper{};
wrapper.templateVersion(10, 20);
}
Your macro ARGS does not define named arguments. You cannot forward the type of unnamed arguments. That's a limitation of the language.
Either forget about using macros, and change your function definiton:
void func(int a, int b) {
otherFunction(a, b);
}
Or change the definition of the macro:
#define ARGS int a, int b
void func(ARGS) {
otherFunction(a, b);
}
That said, nothing beats the template solution. Make sure you use perfect forwarding.
template <typename ...Args>
void templateVersion(Args&& ... args) {
otherFunction(std::forward<Args>(args)...);
}

Variadic operator overloading of the [] in C++

I am looking to use the expressions passed in the operator []. I thought that using variatic template arguments would do the trick but i was wrong...
Is the a way to do this in c++11?
class object {
private:
public:
void values() { std::cout << "finished" << std::endl; }
template <typename T, typename... Type> void values(T arg, Type... args) {
std::cout << arg << " " << std::endl;
values(args...);
}
template<typename... Type> void operator[](Type... args) {
values(args...);
}
};
int main(void) {
object o1 = object();
o1.values(1, 6.2, true, "hello"); // Works fine.
o1[1, 6.2, true]; // Only the last value gets printed eg. true
return 0;
}
The broader objective is that I was asked to make a working syntax of this
let o3 = object [ values 1, "2", true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ]; // no commas are missing
in c++11 using c++11 STL (templates , using , MACROS , operator overloading etc.) . I am slowly trying to figure out how to piece this together
First of all, you need to understand that operator[] can only take exactly one argument. Your templated operator hides an error message that is rather clear about that.
struct foo {
void operator[](int,int);
};
Results in error:
<source>:2:10: error: 'void foo::operator[](int, int)' must have exactly one argument
2 | void operator[](int,int);
| ^~~~~~~~
You can make it a variadic template, but any instantiation with not exactly one argument isn't right.
Franky, this sounds like a trick question. When you write C++ code you better use C++ syntax. If macros are allowed (they shouldn't be) then almost anything is possible. You just need to be aware that you aren't actually writing C++ anymore. Also, it seems a bit odd to merely ask for some syntax to compile. I don't know javascript and wasn't sure what the two lines are supposed to mean, so I only did that: Make it compile somehow.
Anyhow, lets see what can be done.
let o3 = object [ values 1, "2", true, -3.14 ];
I suppose this declares o3 to be an object whose initializer is retrieved from a container called object that can be indexed via values 1, "2", true, -3.14. The line can be made to compile by overloading some operator, and #defineing let to be auto and values to construct an object that collects the index (via its operator,):
For the second line
let o1 = object [ key("x") = -1, key("y") = -2,values 1, "2", true, -3.14 ];
a similar trick can be played with operator, and abusing key::operator=. I interpreted key as constructing some key-value pair,eg key("x") = -1 maps the value -1 to the string "x". What it actually does isn't essential for all the dirty stuff that follows. Once you understood how to misuse operator overloading it can be modified to do something else in the details.
To see that all values are actually passed to operator[] I stole some tuple print function from here: https://stackoverflow.com/a/41171552/4117728
#include <tuple>
#include <string>
#include <typeinfo>
#include <iostream>
#define let auto
//https://stackoverflow.com/a/41171552/4117728
template<class TupType, size_t... I>
void print(const TupType& _tup, std::index_sequence<I...>)
{
std::cout << "(";
(..., (std::cout << (I == 0? "" : ", ") << std::get<I>(_tup)));
std::cout << ")\n";
}
template<class... T>
void print (const std::tuple<T...>& _tup)
{
print(_tup, std::make_index_sequence<sizeof...(T)>());
}
//........................................
struct Object {
template <typename ...T>
struct ObjectIndex {
ObjectIndex() {}
ObjectIndex(std::tuple<T...> ind) : index(ind) {}
std::tuple<T...> index;
template <typename U>
ObjectIndex<T...,U> operator,(const U& u){
return { std::tuple_cat(index,std::make_tuple(u)) };
}
template <typename...U>
ObjectIndex<T...,U...> operator,(const ObjectIndex<U...>& other) {
return { std::tuple_cat(index,other.index) };
}
};
template <typename ...T>
int operator[](ObjectIndex<T...> index){
std::cout << typeid(index.index).name() << "\n";
print(index.index);
return 42;
}
};
struct key {
std::string k;
int val;
key(const std::string& s) : k(s) {}
Object::ObjectIndex<std::string,int> operator=(int v) {
val = v;
return {std::make_tuple(k,val)};
}
};
#define values Object::ObjectIndex<>{} ,
int main() {
Object object;
let o3 = object [ values 1, std::string("2"), true, -3.14 ];
let o1 = object [ key("x") = -1, key("y") = -2,values 1, std::string("2"), true, -3.14 ];
}
Live Demo
Don't do this at home (or anywhere else)!
There was some issue with passing a string literal and I didn't bother to look into that further, so I allowed myself to replace "2" with std::string("2"). I guess with some more fighting through endless error messages this can be fixed too.
I have no clue if the code is anywhere near to what those two lines are really supposed to do. I merely took it as a fun exercise to get it compile somehow. When actually returning something from operator[] I ran out of ideas. I have a hard time to imagine a container with a truly variadic operator[]. I choose the answer that is right always.
TL;DR Can you overload operator[] to take more than one parameter? No. Can you overload it to take a single parameter that encapsulates arbitrary values? Sure.

Is it possible to implement log once in C++20 without macros?

What I am looking for is the log function that will log message, but only once per call site.
It would be useful to log first occurrence of an error, timeout, etc, without spamming the cout/log files.
Traditionally it has been implemented with macros(where they expand to some static bool/counter, you can see LOG_FIRST_N in glog for details), but I wonder if in C++20 it can be done without macros.
What I have tried:
Use std::source_location as template param, based on this answer, does not work since magic of std::source_location::current() does not work as I want it to work.
note: I know I can have one static std::set/std::unordered_set of call sites, but I am interested in solutions that is as efficient as the evil MACRO solution.
As every lambda expression is of different type, you can use lambda expressions to tag calls to the same function.
For example this:
#include <iostream>
template <typename T,typename F>
void once(T t, F f){
static bool first = true;
if (first) {
f();
first = false;
}
}
int main(){
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "B";});
}
}
Prints
AB
However, once([](){},... is a bit unwieldy and it is still tempting to use a macro.
PS: As mentioned in a comment, since C++20 the lambda can be used as default argument for the template and even before you can do:
#include <iostream>
template <typename F,typename T>
void once_impl(F f, T t){
static bool first = true;
if (first) {
f();
first = false;
}
}
template <typename F>
void once(F f) { once_impl(f,[](){});}
int main(){
for (int i=0; i <1000; ++i){
once([](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){ std::cout << "B";});
}
}
if(error)
static const bool error_logged=error_log << "message\n";
the first time error is true, the stream will be written to. Every other time, nothing. It is thread safe; if 2 threads both have the error, it is guaranteed exactly one runs the log code.
error_logged will store true if the write worked, false otherwise.
C++ does not have a way to inject state to the calling location from within a function call (barring coroutines, which are not zero cost). So the state -- "have I called this before, here" -- must be at the calling site.
The amount of state required is minimal; as you can see above, a branch plus a static local is enough.
The evil macros are usually more complex because they want to be usable in more complicated structures, like:
return a?b:(log("error!"), c);
You might wrap the logic in template, and in C++20, lambda can be used as default template argument:
So you might do
template <typename F, typename Tag = decltype([](){})>
// or template <typename F, auto Tag = [](){}>
void simple_do_once(F f /*, Tag={}*/ )
{
static std::once_flag flag;
std::call_once(flag, f);
}
Demo

Does C++ support parameterized function for testing purpose?

I have a lengthy unit test code snippet that I want to run for two functions. I am wondering if there's a way to do this without copy and paste the code and only change the function name?
Say the test code looks like
int main(){
output1 = function(input1);
assert output1 == answer1;
output2 = function(input2);
assert output2 == answer2;
output3 = function(input3);
assert output3 == answer3;
......
outputN = function(inputN);
assert outputN == answerN;
}
Now say I have two function func1 and func2. I want to ran literally the same test for func1 and func2. I am wondering if there's a neat way to do this in C++ without involving some test framework? Thanks in advance for any help.
You can make a function template:
template <typename F, typename R, typename Args...>
void test_func(F f, R&& r, Args&&... args) {
auto output = f(std::forward<Args>(args)...);
assert(output == std::forward<R>(r));
}
then use it like
test_func(&func1, answer1, input1);
test_func(&func2, answer2, input2);
...
Additional explanations:
The parameters and return value are passed by forwarding reference, then their value categories will be reserved when being passed to the function (with the usage of std::forward).
The parameters is declared as parameter pack then you can pass multiple ones with any types.
C++ supports passing parameters to functions ;).
You can pass functions to functions. To keep it simple, I am assuming that all functions you want to test have the same signature. To avoid verbose syntax of function pointers I'd use a template:
template <typename F>
void test_function(F f, std::vector<input_type> input,std::vector<output_type> expected) {
for (size_t i = 0; i < input.size(); ++i) {
assert( f(input[i]) == expected[i]);
}
}
int main() {
test_function( func1, {1,2,3},{2,3,4} );
test_function( func2, {1,2,3},{6,7,8} );
}
PS: From my own experience I can tell you that it isn't worth to put much work into hand-written test facilities. You will find yourself wanting more and more features that a test framework offers out of the box (eg logging test reports). Googletest is something I can recommend.
A solution of C methed is to use fuction pointer. But I recommand lambda fuction pulished in c++11. u can use as follow:
template<typename Func>
void test(intput in, output out, Func func) {
answer = func(in);
assert(out == answer);
}
void main() {
intput intput1;
output output1;
test(input1, output1, [&](intput in)->output{return func1(in)});
test(input1, output1, [&](intput in)->output{return func2(in)});
}
After all, u should add compile para:-std=c++11 while using g++ compiler.
Here's my new take, this should compile. It's built in layers so you can see how to expand each layer as you see fit. It doesn't work exactly as your example does, there are copies being made of your input data and there is no assignment operation for the output. You should take these into account and adjust accordingly (if required).
// Example program
#include <functional>
#include <assert.h>
#include <vector>
#include <utility>
// function to test
int func1(int p_param)
{
return p_param;
}
// function to test
int func2(int p_param)
{
return p_param;
}
// Test runner base
template <typename TFunction, typename TInput, typename TOutput>
void test_runner(TFunction f, std::vector < std::pair<TInput, TOutput> > p_testparameters)
{
for (auto pair : p_testparameters)
{
assert(f(pair.first) == pair.second);
}
}
// Specific test 1
template <typename TFunction>
void test1(TFunction f)
{
test_runner<TFunction, int, int>(f, { {1,1},{2,2},{3,3} });
}
// Specific test 2
template <typename TFunction>
void test2(TFunction f)
{
test_runner<TFunction, int, int>(f, { {10,10},{20,20},{30,30} });
}
// Run tests for function
template <typename TFunction>
void runTests(TFunction f)
{
test1(f);
test2(f);
}
int main() {
runTests(func1);
runTests(func2);
return 0;
}

C++ member function pointer with different arguments - or is this bad anyway?

Even though I fear that you will tell me that this topic was covered several time, I dare to ask it, since I was not able to generate a solution. Probably I was just looking for the wrong thing...
Assume that I have a function which receives a "mode" from some external function. Depending on the mode, the function will call different member functions of the same object. This works well for me with member function without any argument, but I did not find out how to extend it to members with arguments. In the real world application, the arguments are not int/float but a more complex classes and the call is nested inside different loops, so I would need to put switch statements several times which I consider ugly.
Question A: Is it possible to easily add support for member functions with arguments based on the existing design? If yes, how does one do that? If possible without external libraries...
Question B: Is this a completely wrong/bad approach? How would I do it better?
Thanks a lot for your help and explanations.
Chris
header excerpt:
typedef void (Object::*memberFunction)();
class Object
{
void memberFnNoArg();
void memberFnWithIntArg(int arg);
void memberFnWithFloatArg(float arg);
}
cpp excerpt:
void function()
{
int mode = getModeFromSomewhere();
int intArg = 33;
float floatArg = 66.6;
switch(mode)
{
case 1:
process(&Object::memberFnNoArg);
break;
case 2:
process(&Object::memberFnWithIntArg, ???); // how can I pass arg?
break;
case 3:
process(&Object::memberFnWithFlaotArg, ???); // how can I pass arg?
break;
default:
// do nothing;
}
}
void process(Object::memberFunction func)
{
Object object;
// loops, called several times, ...
(object.*func)(); // how do I handle different arguments?
}
Wrapping the algorithm in a functor is the right approach, and std::function is a nice functor provided by the Standard library.
But using boost::bind or even std::bind, as suggested by Tomek, is really ugly IMO, and rapidly gets out of control when binding multiple arguments.
If you have a recent compiler you can use a lambda instead, which makes Tomek's example look like:
std::function<void(Object*)> f =
[](Object* const that){ that->memberFnNoArg(); };
int int_value = 22;
std::function<void(Object*)> f2 =
[int_value](Object* const that){ that->memberFnIntArg(int_value); };
Object o;
f(&o);
f2(&o);
There are a few characters to set up the lambda, but the member access syntax is extremely natural and it's obvious how you make changes.
Of course, you can make the parameter a reference to the object if you really want, but I prefer pointers here.
Have a look at std::function and std::bind, they seem to fit perfectly what you need.
EDIT:
std::function<void(Object &)> f = &Object::memberFnNoArg;
std::function<void(Object &)> f2 = std::bind(&Object::memberFnWithIntArg, _1, 22);
Object o;
f(o);
f2(o);
should work out of a box as far as I remember.
Is this what you need?
You could use a varadic template function:
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args)
{
Object object;
// loops, called several times, ...
(object.*func)(args...);
}
Here is a full example:
#include <iostream>
struct Object
{
void memberFnNoArg()
{
std::cout << "Object::memberFnNoArg()\n";
}
void memberFnWithIntArg(int arg)
{
std::cout << "Object::memberFnWithIntArg(" << arg << ")\n";
}
void memberFnWithFloatArg(float arg)
{
std::cout << "Object::memberFnWithFloatArg(" << arg << ")\n";
}
};
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args)
{
Object object;
// loops, called several times, ...
(object.*func)(args...);
}
int main()
{
process(&Object::memberFnNoArg);
process(&Object::memberFnWithIntArg,5);
process(&Object::memberFnWithFloatArg,2.7F);
return 0;
}
One way I see around this would be to use a variable arguments (pretty much like printf, sprintf does it). (Or maybe with stdc libraries, passing a list of different types.)
The reason is, that the argument list is part of the function pointer type, so you'd essentially need a process function with variable arguments and then the memberFunction probably needs to be one of that type too.
Below is a plain (non member) sample of how to pick up variable arguments (member functions would essentially work the same). See stdarg.h.
typedef void (*var_function)(int typearg, ...);
void print_arg(int typearg, ...)
{
va_list ap;
int i;
va_start(ap, typearg);
if (typearg==1) { // int
int i= va_arg(ap, int);
printf("%d ", i);
}
else
if (typearg==2) { // float
float f= va_arg(ap, float);
printf("%f ", f);
}
else
if (typearg==3) { // char *
char *s= va_arg(ap, char *);
printf("%s ", s);
}
....
va_end(ap);
}
// calling function with different types
int main()
{
print_arg(1, 999);
print_arg(2, 3.1415926);
print_arg(3, "Hello");
....
process(print_arg, 3, "via pointer);
Sounds like packaged_task. Also check out Tomek's suggestion.
Though IRL I'd go ahead asking lots of questions on why you need it in the first place. Possibly your work could be better covered using std::future or other higher level facility,
Can't each function (memberFn**) be a member of argument classes ?
class BaseArg
{
virtual void Fn() = 0;
};
class IntArg : public BaseArg
{
void Fn();
};
class FloatArg : public BaseArg
{
void Fn();
};
void function()
{
int mode = getModeFromSomewhere();
BaseArg* pArg;
if ( mode ... ){
pArg = new IntArg( 33 );
}
else {
pArg = new FloatArg( 66.6 );
}
pArg->Fn(); // Call the right function without a switch
// and without knowing the arguments
}
Same as other answers, but to show for member methods:
#include <iostream>
class Object
{
public:
void memberFnNoArg()
{
std::cout << "Object::memberFnNoArg()\n";
}
void memberFnWithIntArg(int arg)
{
std::cout << "Object::memberFnWithIntArg(" << arg << ")\n";
}
void memberFnWithFloatArg(float arg)
{
std::cout << "Object::memberFnWithFloatArg(" << arg << ")\n";
}
bool memberFnWithBoolReturn(int)
{
return true;
}
template <typename... Args>
void process(void (Object::*func)(Args...),Args... args);
// overload process
template <typename... Args>
bool process(bool (Object::*func)(Args...),Args... args);
};
template <typename... Args>
void process( void (Object::*func)(Args...),class Object* obj,Args... args)
{
(obj->*func)(args...);
}
template <typename... Args>
bool process( bool (Object::*func)(Args...),class Object* obj,Args... args)
{
return ((obj->*func)(args...)) ;
}
int main()
{
Object object;
process(&Object::memberFnNoArg,&object);
process(&Object::memberFnWithIntArg,&object,5);
process(&Object::memberFnWithFloatArg,&object,2.7F);
// overloaded process
printf("%d\n",process(&Object::memberFnWithBoolReturn,&object,1));
return 0;
}