Concat使用变长的参数模板来接受不同的字符串(string, const char*),为了保证string不会多次分配空间,要先求出所有字符长度之和,分配空间后在依次添加。
变长求和函数:
static int _Sum() { return 0; } template<typename T, typename... TArgs> static int _Sum(T t, TArgs... args) { return t + _Sum(args...); }
调用_Sum时,第一个参数会适配T,剩下的作为参数包适配TArgs,直到参数包为空时调用普通的_Sum函数结束递归。
在准备两个版本的求字符串长度的重载。
static size_t Size(const string& str) { return str.size(); } static size_t Size(const char* str) { return ::strlen(str); }
对参数包进行函数执行和展开,Size会求出每个字符串的大小后变成一个参数包,在把此参数包传入_Sum,_Sum进行递归求和后返回,在对string预分配内存。
template<typename... T> static string Concat(const T&... args) { size_t size = _Sum(Size(args)...); string str; str.reserve(size + 1); return str; }
然后就是为这个分配了内存的string填充参数包的内容,同样,声明两个字符串版本的添加。
static void _AppendStr(string& str, const char* nstr) { str.append(nstr); } static void _AppendStr(string& str, const string nstr) { str.append(nstr.c_str()); }
像上面的变长求和一样,进行递归添加,每次递归把参数包的一个参数添加,然后对剩下的参数包继续传递递归。
static void _Append(string& str) {} template<typename T, typename... TArgs> static void _Append(string& str, const T& nstr, TArgs&&... args) { _AppendStr(str, nstr); _Append(str, args...); }
完整的Concat函数
template<typename... T> static string Concat(const T&... args) { size_t size = _Sum(Size(args)...); string str; str.reserve(size + 1); _Append(str, args...); return str; }
文章评论