I believe this is possible using the ideal call forwarding argument and Variadic.
joinStr.hpp:
class joinStr { public: template<typename... Args> joinStr(const std::string& first, Args&&... args): ret(""), size(0) { size = first.length(); getSize((args)...); std::cout << "before reserve : " << ret.capacity() << std::endl; ret.reserve(size); std::cout << "after reserve : " << ret.capacity() << std::endl; ret.append(first); join(std::forward<Args>(args)...); } ~joinStr() {} std::string getStr() { std::cout << ret << std::endl; return ret; } private: std::string ret; int size; int getSize() { std::cout << "size : " << size << std::endl; return size; } template<typename... Args> int getSize(const std::string& first, const Args&... args) { size += first.length(); return getSize((args)...); } template<typename... Args> int getSize(char* first, const Args&... args) { size += strlen(first); return getSize((args)...); } template<typename... Args> int getSize(const char* first, const Args&... args) { size += strlen(first); return getSize((args)...); } void join() { std::cout << "Final capacity : " << ret.capacity() << std::endl; } template<typename... Args> void join(const std::string& first, Args&&... args) { ret.append(first); join(std::forward<Args>(args)...); } template<typename... Args> void join(char* first, Args&&... args) { ret.append(first); join(std::forward<Args>(args)...); } template<typename... Args> void join(const char* first, Args&&... args) { ret.append(first); join(std::forward<Args>(args)...); } };
main:
int main() { std::string s1 = "hello"; std::string s2 = "world !"; std::string s3 = "meatpopsicle"; const char* s4 = "__yeah__"; joinStr c(s1, s2, s3, s4); return 1; }
Note that I wrapped it inside the class, but you can do the same outside the class.
As a bonus, it works with both std :: string, const char *, and char *.
Edit : fixed reuse of moved values ββin getSize and added template for const char * after Caleth clause
Edit 2 : A version that allows passing the size_t field after const char * instead of using strlen.
class joinStr { public: template<typename... Args> joinStr(const std::string& first, Args&&... args): ret(""), size(0) { size = first.length(); getSize(args...); std::cout << "before reserve : " << ret.capacity() << std::endl; ret.reserve(size); std::cout << "after reserve : " << ret.capacity() << std::endl; ret.append(first); join(std::forward<Args>(args)...); } ~joinStr() {} std::string getStr() { std::cout << ret << std::endl; return ret; } private: std::string ret; int size; int getSize() { std::cout << "size : " << size << std::endl; return size; } template<typename... Args> int getSize(const std::string& first, const Args&... args) { size += first.length(); return getSize((args)...); }
main:
int main() { std::string s1 = "hello"; std::string s2 = "world !"; std::string s3 = "meatpopsicle"; const char* s4 = "__yeah__"; joinStr c(s1, s2, s3, s4, (size_t)8); return 1; }