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