0

Question

Is there a way to pass arguments from a "sender" function to a "receiver" function in C++?


Expectation/ Theory

void print(const char character) { std::putchar(character); }
void print(char message[], unsigned length) {
    for (unsigned iterator = 0u; iterator ^ length; iterator += 1)
        print(*(message + iterator));
}

void println(...) { print(...); print('\n'); std::fflush(stdout); }

In this example:
println is the "sender" function and
print is the "receiver" function.

The print function is to accept all arguments of the println function as denoted by the example ... syntax.


Context

I do know of template functions in C++ and how it can rectify the former example to be

void print(const char);
void print(char[], unsigned); // They’ve been defined before already…

template <typename... types>
void println(types... arguments) { print(arguments...); print('\n'); std::fflush(stdout); }

But I want to see if there is another approach to this problem — without fairly recent C++-only features i.e.: how was this problem solved in C?

I code in a C-style manner (using C features over C++ features) in C++ because I want to know how to build C++ features personally.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Lapys
  • 936
  • 2
  • 11
  • 27
  • [This](https://stackoverflow.com/questions/150543/forward-an-invocation-of-a-variadic-function-in-c) seems similar – n314159 Dec 07 '19 at 21:38
  • Very similar... There are a few approaches to the problem I could try. I'll stick around longer to see if there could be *maybe* any more answers... Otherwise I'll close the question, then – Lapys Dec 07 '19 at 21:54
  • "I want to know how to build C++ features personally" -> A new function is instantiated from the template every time you call `println` with a different set of `types...`. You could just literally do that (Create two `println` overloads as well) – Artyer Dec 07 '19 at 21:59
  • @Artyer Yea but what if there are more than just a *few* `print` functions to have a `println` variation for. – Lapys Dec 07 '19 at 22:40

1 Answers1

1

how was this problem solved in C?

In C use macros. A function macro with only ... and pass the arguments to the function:

#define println(...)  do { \
        print(__VA_ARGS__); \
        print('\n'); \
        std::fflush(stdout); \
} while(0)

There is one limitation - calling such function macro without any arguments is not allowed according to ISO C standard.

It's common in C to use a gcc extension of applying ## preprocessor operator to __VA_ARGS__ and pass additional parameters to the print function, like __func__ or __LINE__ or __FILE__ for debugging purposes. Like ex. here or here or here (just a few first results from a short google search).

#define println(str, ...)  do { \
        print("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
        fflush(stdout); \
} while(0)
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • **Hmm, what if I don't want to globally define the `println` macro?** Here's an impractical example: I create a `print` function in a local namespace and want it to have a `printf` and `println` variation that rely on the `print` function, but defining `printf` as a macro completely overrides the native `printf` function provided by the C standard library. – Lapys Dec 07 '19 at 21:49
  • I don't understand the question. What does it mean to "globally define"? How can you define "not globally"? Didn't you answer yourself? In C there are no namespaces and sometimes names clash. Just pick a unique name. – KamilCuk Dec 07 '19 at 22:13
  • Ah, sorry. I'm using C++ so there are `namespace` scopes that allow variables and functions to be defined within the namespace alone – Lapys Dec 07 '19 at 22:42