Created
November 23, 2014 17:15
-
-
Save valmat/fdb37d1b741d5c12336d to your computer and use it in GitHub Desktop.
Optimized string concatenation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
/** | |
* Optimized aggregating strings | |
* used Args pack | |
*/ | |
template <unsigned short size> | |
struct StrJoinInitializer | |
{ | |
template <typename ...Args> | |
StrJoinInitializer(Args&&... args) : aggr{helper(std::forward<Args>(args))...} {} | |
/** | |
* Cast to a std::string | |
*/ | |
operator std::string () const | |
{ | |
size_t len = 0; | |
for(unsigned short i = 0; i < size; ++i) { | |
len += aggr[i].size()+1; | |
} | |
--len; | |
std::string rez; | |
rez.reserve(len); | |
rez += aggr[0]; | |
for(unsigned short i = 1; i < size; ++i) { | |
rez += _sep; | |
rez += aggr[i]; | |
} | |
return std::move(rez); | |
} | |
StrJoinInitializer& sep(char s) & | |
{ | |
_sep = s; | |
return *this; | |
} | |
StrJoinInitializer&& sep(char s) && | |
{ | |
_sep = s; | |
return std::move(*this); | |
} | |
StrJoinInitializer(const StrJoinInitializer& that) = delete; | |
StrJoinInitializer(StrJoinInitializer&& that) = default; | |
private: | |
std::string& helper(std::string& s) { return s;} | |
const std::string& helper(const std::string& s) { return s;} | |
std::string&& helper(std::string&& s) { return std::move(s);} | |
std::string helper(bool x) { return (x ? "1" : "0");} | |
std::string helper(const char *x) { return std::string(x);} | |
std::string helper(char x) { return std::string(1, x);} | |
std::string helper(unsigned char x) { return std::to_string(x);} | |
template<typename T> | |
typename std::enable_if<std::is_arithmetic<T>::value, std::string>::type | |
helper(T&& x) { return std::to_string(x);} | |
std::string aggr[size]; | |
char _sep = ':'; | |
}; | |
// output stream operator | |
template <unsigned short size> | |
std::ostream &operator<<(std::ostream &stream, const StrJoinInitializer<size>& x) | |
{ | |
return stream << static_cast<std::string>(x); | |
} | |
template <typename ...Args> | |
StrJoinInitializer<sizeof...(Args)> strjoin(Args&&... args) | |
{ | |
return StrJoinInitializer<sizeof...(Args)>(std::forward<Args>(args)...); | |
} | |
/** | |
* Optimized aggregating strings | |
* used initializer_list | |
*/ | |
std::string strjoin(std::initializer_list<std::string> aggr, const char sep = ':') | |
{ | |
size_t sz = 0; | |
for(auto &it: aggr) { sz += it.size()+1;} | |
--sz; | |
std::string rez; | |
rez.reserve(sz); | |
auto it = aggr.begin(), itend = aggr.end(); | |
rez += *(it++); | |
while( it != itend) { rez += sep + *(it++); } | |
return rez; | |
} | |
int main() { | |
using std::cout; | |
using std::endl; | |
using std::string; | |
string str1("str1"); | |
string str2("str2"); | |
const string str3("str3"); | |
unsigned char q1 = 11; | |
const unsigned char q2 = 12; | |
string rez1 = strjoin(str1, str2, str3, string("str4"), 4, -5, true, false, 0, "c_str", '%', q1, q2).sep('~'); | |
cout << rez1 << endl; | |
cout << strjoin(str1, str2) << endl; | |
string rez2 = strjoin({str1, str2, str3, string("str4"), "str5"}); | |
cout << rez2 << endl; | |
cout << strjoin({str1, str2, str3}, '~') << endl; | |
return 0; | |
} | |
/* | |
* g++ -std=c++11 strjoin.cpp && ./a.out | |
* or | |
* clang++ -std=c++11 strjoin.cpp && ./a.out | |
* | |
* |output: | |
* |str1~str2~str3~str4~4~-5~1~0~0~c_str~%~11~12 | |
* |str1:str2 | |
* |str1:str2:str3:str4:str5 | |
* |str1~str2~str3 | |
* | |
* | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment