1

Permit me to say that I know this question does not fit into most conventions (if any at all) but out of curiosity and love for the programming language (C++) I'll ask this question anyway. Feel free to correct me with your answers or comments below.

The Question:

"Can we make variadic functions in C++ that accept arguments of multiple (and possibly previously unknown) data types and how would it be implemented?"

Example:

JavaScript Sample

function buildArgs(... args) {
    let iterator = 0,
        length = args.length;

    for (iterator; iterator != length; iterator += 1) {
        let arg = args[iterator];
        build(arg)
    }
}

buildArgs(1); // Valid
buildArgs(1, "Hello"); // Valid
buildArgs(1, "Hello", null) // Valid

(Hypothetical) C++ Sample:

template <class... Args, typename data>
inline void buildArgs(Args... args) {
    int iterator = 0,
        length = sizeof args;

    for (iterator; iterator != length; iterator += 1) {
        data arg = args[iterator];
        build(arg);
    }
}

buildArgs(1); // Valid
buildArgs(1, "Hello"); // Valid
buildArgs(1, "Hello", NULL); // Valid

From the examples given, the arguments considered valid to the function buildArgs can be of any data type (char, int, std::string and so on) while the function buildArgs can accept any number of those valid arguments.

I've already done some minor research on variadic functions and templates in C++ but nothing I've seen has answered this question yet.

Again, I can not speak for the practicality of this feature but I would love to very much see if it is possible.

Links:

Variadic Functions with Different Types of Arguments in C: variadic functions with different types of arguments in c

Accept all Types as Argument in Function: Accept all types as argument in function

C Programming : https://en.wikibooks.org/wiki/C_Programming/stdarg.h

C++ Reference - Parameter Pack: https://en.cppreference.com/w/cpp/language/parameter_pack

C++ Reference - Fold Expressions: https://en.cppreference.com/w/cpp/language/fold

Variable Number of Arguments in C: Variable number of arguments in C++?

Conclusion:

Thank you for taking the time to read my question, and even more thanks for answering.

Lapys
  • 936
  • 2
  • 11
  • 27
  • 2
    not everybody who knows c++ also knows javascript, thus it would help if you also describe more in detail in words what you mean by "unknown types of parameters" – 463035818_is_not_an_ai Aug 17 '18 at 10:14
  • 2
    It is possible, however unlike in js it doesn't turn it into an array/tuple : it's a variadic pack that you need to unpack in order to use it. – Vivick Aug 17 '18 at 10:15
  • 2
    in other words: why is variadic templates not the the answer to your question? – 463035818_is_not_an_ai Aug 17 '18 at 10:15
  • 4
    The last question you link to already has an example of a variadic function that takes different types of arguments. Not sure what more you want. – Mat Aug 17 '18 at 10:16
  • 3
    what you are searching for is actually not that hypothetical, but variadic templates allow you to do exatcly this: sloppy speaking unknown number, any type you like. I dont really understand what you are asking, either you didnt know variadic templates or there is something more you want that isnt clear from the question – 463035818_is_not_an_ai Aug 17 '18 at 10:25
  • I see, I might have missed something when I was searching for the solution. You are right Mat, the last link is similar to what I'm asking (although it's type-restrictive for the first parameter). @user463035818 thanks for the comments, I was not completely aware of variadic templates at the time so I'll get right on that. – Lapys Aug 17 '18 at 10:28
  • 1
    If I remember right, JavaScript has reflection. I can ask at run-time an object what it is. Beside of RTTI, such things does not exist in C++ (if not programmed in code). Hence, the suitable processing of "unknown" arguments must happen at compile time - using the usual meta-programming "tricks" to apply the proper handling of an argument according to its type. The C var-arg macros are a bit different. Example: `printf()` - You have to provide some information somehow to read the variadic arguments properly. – Scheff's Cat Aug 17 '18 at 10:29
  • Possible duplicate of [Variable number of arguments in C++?](https://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c) – Lapys Aug 17 '18 at 10:29

3 Answers3

2

Parameter packs are current C++ way to do it:

template<typename... Args> auto f(Args &&...args);

With packs, you can do not much but still something:

I. Store them in tuples or (when possible) arrays or initialization_lists:

auto t = std::tuple(std::forward<Args>(args)...);
CommonType a[] = {args...};
std::set<int> mySet{args...};

II. Use them as function arguments (see tuple construction above.) One pack-aware operator in C++ is sizeof...:

std::size_t currentArity = sizeof...(Args);

III. Fold packs:

bool any = (args || ...);
(std::cout << ... << args);

set::set<int> myOtherSet;
(myOtherSet.insert(args), ...);

And so forth.

bipll
  • 11,747
  • 1
  • 18
  • 32
0

In case of C++11 it is much more complicated: Live example.

template <typename T>
void printArgs(T &&x)
{
    std::cout << std::forward<T>(x) << " - ";
}

template <typename FirstT, typename ...Args>
void printArgs(FirstT &&first, Args&&...remaining)
{
    printArgs(std::forward<FirstT>(first));
    printArgs(std::forward<Args>(remaining)...);
}

As you can see you do not have argument iterator. Instead pseudo recursion is used.
Also something strange called perfect forwarding should be taken into account.

Here you can see live example which gives debug information

Question was:

"Can we make variadic functions in C++ that accept arguments of multiple (and possibly previously unknown) data types and how would it be implemented?

Answer is YES. Templates in C++ are instantiated when they are used. So by default they work with any type until some problem inside is encounter, for example some functionality is not available for specific type.

In example above you can define custom type, and printArgs will fail since there is no operator<<(std::ostream &, const NewType &) for new type. To solve it you have to simply provide such operator and printArgs will start working for new type.

There are other approaches like CRTP (Curiously recurring template pattern) and so on. Template topic in C++ is quite long and complex.

Marek R
  • 32,568
  • 6
  • 55
  • 140
0

Can we make variadic functions in C++ that accept arguments of multiple (and possibly previously unknown) data types?

Yes. There are library facilities in the header <cstdarg> to make this easier.

They are:
- va_start (enables access to variadic function arguments),
- va_arg (accesses the next variadic function argument),
- va_copy (introduced in C++11 which makes a copy of the variadic function arguments,
- va_end (which ends traversal of the variadic function arguments) and
- va_list (which holds the information needed by va_start, va_arg, va_end, and va_copy).

Additionally C, Go, C#, PHP, Java, JavaScript, Python, Perl 6 support this feature.

P.W
  • 26,289
  • 6
  • 39
  • 76