1

I currently have

std::stringstream ss;
ss << "hey"<<" "<< "hey"<<" "<< "hey"<<" "....// here I want to be able to pass different kinds of messages
std::string s(ss.str());    
write(to_chat_message(s));

I want to convert the part before write to a function so that I can simply do write(to_chat_message("hey"," ","hey"," ","hey"," ",...));

How should I write this new overloaded to_chat_message() method

  • This may be helpful: http://stackoverflow.com/questions/1657883/variable-number-of-arguments-in-c It covers C++ and C++11 as well as variable number of same and different arguments. – Shafik Yaghmour May 30 '13 at 17:18
  • 2
    Are you asking for a way to accept variable numbers of arguments of any type, or specifically if there is a way to accept only a variable number of strings? – Gabe May 30 '13 at 17:19
  • only for strings....I mean char arrays - "string1" –  May 30 '13 at 17:23
  • Is c++11 (particulary variadic templates) an option for you? – Grizzly May 30 '13 at 17:25
  • no i dont ve c++11, i m on vs2008 –  May 30 '13 at 17:25
  • 2
    why don't you simply use a vector of strings? – leemes May 30 '13 at 17:27
  • I want to able to pass the arguments like - ("one", " ", "two", ...) –  May 30 '13 at 17:28
  • The best you can probably do (assuming you want to pass actual strings and not char*) is overload the function for each number of parameters you want to support, concat the strings before passing them to the function somehow or passing them in a container (vector). Any other solution is very likely to involve some serious application of black magic. If you want to pass only `const char*` (aka evil c-style strings), you could possibly use c-style varargs of course. – Grizzly May 30 '13 at 17:28

3 Answers3

5

If you're only taking in strings, just use a vector of strings. Parse over the vector in the method. Based on your question there doesn't appear to be a need for variable arguments.

Captain Skyhawk
  • 3,499
  • 2
  • 25
  • 39
1

Since you obviously only want strings and char-arrays that are convertible to strings, you will only need a variable number of string arguments.

The first thing that comes to mind is std::vector.

std::string to_chat_message(std::vector<std::string> v) {
  //do something with the strings in v...
}

in C++11

this can be very easily done together with initializer-lists:

//...
string str{"meh"};
write(to_chat_message({"hey", " ", "hey", str, "what?"}));

For convenience, to get rid of the curly braces, you could write a variadic template:

template <class... Args>
std::string to_chat_message(Args&&... args) {
  return to_chat_message({ std::forward<Args>(args)... });
}

// and now...
write(to_chat_message("hey", " ", "hey", str, "what?"));

in C++03

you have neither variadic templates nor initializer-lists. But you have boost.assign:

#include <boost/assign/list_of.hpp>

using boost::assign::list_of;
write(to_chat_message(list_of<std::string>("hey")(" ")("hey")(str)("what?")));

Thats a bot more verbose, so you could roll a convenience function, but that would have to rely on boosts detail implementation of list_of:

boost::assign::assign_detail::generic_list<std::string> sl(std::string const& str)
{ return boost::assign::list_of(str); }

write(to_chat_message(sl("hey")(" ")("hey")(str)("what?")));

Or you roll your very own implementation, just for this purpose:

struct ToChatMessage {
  std::vector<std::string> strings;

  ToChatMessage(std::string const& str) {strings.push_back(str);}

  operator std::string() const { return to_chat_message(strings); }

  ToChatMessage& operator()(std::string const& str) {
    strings.push_back(str);
    return *this;
  }
};


write(ToChatMessage("hey")(" ")("hey")(str)("what?"));

This does mostly what list_of does: with the leftmost call (constructor) you create an object that holds a vector of strings and push the first argument into that vector. The other calls (operator()) push more values into the vector. You can chain thise calls because the operator() returns a reference to the object. Finally, since write() accepts only strings and not objects of type ToChatMessage, that object is converted into a string by calling operator string() and thus passing the vector of strings to to_chat_message.

Instead of overloading operator() you could of course use other operators, depending on what you'd like the call to look like, e.g. operator<<:

write(ToChatMessage() << "hey" << " " << "hey" << str << "what?" );

Of course there is the possibility to overload to_chat_message with accepting one through N arguments, but that would mean you'd either have to repeat mostly the same stuff manually N times, your you would ahve to use preprocessor magic like Boost.Preprocessor and create an unreadable, hard to maintain and nondebuggable mess defininig all those overloads.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
0

You will need to use the standard C/C++ method of passing a variable number of parameters to a function. As Shafik mentioned you should look at "Variable Number of Arguments in C" The accepted answer should have all of the information that you need to do this.

Community
  • 1
  • 1
anotherdjohnson
  • 303
  • 1
  • 5
  • 13