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.