Variable number of arguments in C++?

Viewed 455128

How can I write a function that accepts a variable number of arguments? Is this possible, how?

18 Answers

Using variadic templates, example to reproduce console.log as seen in JavaScript:

Console console;
console.log("bunch", "of", "arguments");
console.warn("or some numbers:", 1, 2, 3);
console.error("just a prank", "bro");

Filename e.g. js_console.h:

#include <iostream>
#include <utility>

class Console {
protected:
    template <typename T>
    void log_argument(T t) {
        std::cout << t << " ";
    }
public:
    template <typename... Args>
    void log(Args&&... args) {
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }

    template <typename... Args>
    void warn(Args&&... args) {
        cout << "WARNING: ";
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }

    template <typename... Args>
    void error(Args&&... args) {
        cout << "ERROR: ";
        int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
        cout << endl;
    }
};

C++ 11 with color code support

  • Is generic and works for all dataypes
  • Works like JavaScript console.log(1,"23")
  • Supports color codes for info, warning, error.
  • Example:
    enter image description here
#pragma once
#include <iostream>
#include <string>

const std::string RED = "\e[0;91m";
const std::string BLUE = "\e[0;96m";
const std::string YELLOW = "\e[0;93m";

class Logger {
private:
  enum class Severity { INFO, WARN, ERROR };

  static void print_colored(const char *log, Severity severity) {
    const char *color_code = nullptr;

    switch (severity) {
    case Severity::INFO:
      color_code = BLUE.c_str();
      break;
    case Severity::WARN:
      color_code = YELLOW.c_str();
      break;
    case Severity::ERROR:
      color_code = RED.c_str();
      break;
    }

    std::cout << "\033" << color_code << log << "\033[0m -- ";
  }

  template <class Args> static void print_args(Args args) {
    std::cout << args << " ";
  }

public:
  template <class... Args> static void info(Args &&...args) {
    print_colored("[INFO] ", Severity::INFO);
    int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
    std::cout << std::endl;
  }

  template <class... Args> static void warn(Args &&...args) {
    print_colored("[WARN] ", Severity::WARN);
    int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
    std::cout << std::endl;
  }

  template <class... Args> static void error(Args &&...args) {
    print_colored("[ERROR]", Severity::ERROR);
    int dummy[] = {0, ((void)print_args(std::forward<Args>(args)), 0)...};
    std::cout << std::endl;
  }
};

// spawn: allocate and initialize (a simple function)
template<typename T>
T * spawn(size_t n, ...){
  T * arr = new T[n];
  va_list ap;
  va_start(ap, n);
  for (size_t i = 0; i < n; i++)
    T[i] = va_arg(ap,T);
  return arr;
}

User writes:

auto arr = spawn<float> (3, 0.1,0.2,0.3);

Semantically, this looks and feels exactly like an n-argument function. Under the hood, you might unpack it one way or the other.

It is possible now...using boost any and templates In this case, arguments type can be mixed

#include <boost/any.hpp>
#include <iostream>

#include <vector>
using boost::any_cast;

template <typename T, typename... Types> 
void Alert(T var1,Types... var2) 
{ 

    std::vector<boost::any> a(  {var1,var2...});

    for (int i = 0; i < a.size();i++)
    {

    if (a[i].type() == typeid(int))
    {
        std::cout << "int "  << boost::any_cast<int> (a[i]) << std::endl;
    }
    if (a[i].type() == typeid(double))
    {
        std::cout << "double "  << boost::any_cast<double> (a[i]) << std::endl;
    }
    if (a[i].type() == typeid(const char*))
    {
        std::cout << "char* " << boost::any_cast<const char*> (a[i]) <<std::endl;
    }
    // etc
    }

} 


void main()
{
    Alert("something",0,0,0.3);
}
int fun(int n_args, ...) {
   int *p = &n_args; 
   int s = sizeof(int);
   p += s + s - 1;
   for(int i = 0; i < n_args; i++) {
     printf("A1 %d!\n", *p);
     p += 2;
   }
}

Plain version

Related