Skip to content

Instantly share code, notes, and snippets.

@valmat
Created November 23, 2014 17:15
Show Gist options
  • Save valmat/fdb37d1b741d5c12336d to your computer and use it in GitHub Desktop.
Save valmat/fdb37d1b741d5c12336d to your computer and use it in GitHub Desktop.
Optimized string concatenation
#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