MBZ
MBZ

Reputation: 27632

C++ template function with unknown number of arguments

this is probably a useless problem but it stuck on my mind for few hours.

I wanna write a function which accepts some (POD) arguments, convert them to string and return the concatenation. for example

template<typename A, typename B>
string ToString(A a, B b)
{
    stringstream ss;
    ss << a << b;
    return ss.str();
}

pretty easy, huh? but it get pretty tough (for me of course) when I wanna write the same function with unknown number of arguments.

is it even possible? any solution?

Upvotes: 2

Views: 4992

Answers (3)

Nordic Mainframe
Nordic Mainframe

Reputation: 28767

Almost like the real thing :-)

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

template<class L,class R>
struct cons_t
{
    const L &l; const R &r;
    cons_t(const L &_l, const R &_r) : l(_l),r(_r) {}
};
template<>
struct cons_t<void,void>{};
typedef cons_t<void,void> cons;

template<class L,class R,class A>
cons_t< cons_t<L,R>, A> operator , (const cons_t<L,R> &l, const A &arg)
{
    return cons_t< cons_t<L,R>, A>(l,arg);
}
void to_stream(stringstream &s, const cons_t<void,void> &) { }
template<typename L, typename R>
void to_stream(stringstream &s, const cons_t<L,R> &c)
{
    to_stream(s, c.l); 
    s << c.r;
}
template<typename L, typename R>
string to_string(const cons_t<L,R> &c)
{
    stringstream ss;
    to_stream(ss,c);
    return ss.str();
}

#define ToString(...) to_string((cons(),__VA_ARGS__))
int main()
{
    cout << ToString(1,2,"Hi There",3.14159);
}

Upvotes: 5

Jon
Jon

Reputation: 1047

I know this is probably an academic problem, and so a work around solution is probably not what you want.

But.

A simple way to handle this in real life would be to pass in a List, or Array, of objects, rather than have multiple parameters.
You know, like Main()

Upvotes: 1

jpalecek
jpalecek

Reputation: 47770

In C++03, no. All you can do is create overloads with different number of arguments:

template<typename A, typename B>
string ToString(A a, B b)
{
    stringstream ss;
    ss << a << b;
    return ss.str();
}

template<typename A, typename B, typename C>
string ToString(A a, B b, C c)
{
    stringstream ss;
    ss << a << b << c;
    return ss.str();
}

This can be automated (somewhat) with the Boost.Preprocessor library.

In C++0x, you can use variadic templates like this:

#include <iostream>

void f()
{
}

template <class T, class ... Ts>
void f(const T& a, const Ts&... args)
{
  std::cout << a;
  f(args...);
}

Upvotes: 11

Related Questions