views:

106

answers:

3

Hi,

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?

+8  A: 

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...);
}
jpalecek
This is correct. Only in C++0x with variadic templates can this actually be accomplished.
DeadMG
+3  A: 

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);
}
Luther Blissett
INCREDIBLE! :)thank you so much :)
MBZ
+1  A: 

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()

Jon
hhhmmm, I'm not sure get with you meant by a List, or Array.is it possible to make a list which accepts _any kind of data_?I know it's possible is C# where everything is _object_ but what about C++?
MBZ
Well you can use a void pointer. You will then have to cast it to something usable inside the method, and do some checking to get its type.Or depending on your application you could put in a superclass for the classes you expect to pass in. For example << appears to belong to the ostream (NOTE: my c++ syntax is a little rusty these days!)
Jon