Skip to content

Commit

Permalink
basic_strcat and basic_string_builder
Browse files Browse the repository at this point in the history
  • Loading branch information
jm4R committed Oct 23, 2019
1 parent 3479cde commit dda2c91
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 19 deletions.
32 changes: 32 additions & 0 deletions include/fast_strcat/strcat.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef jm4R_STRCAT
#define jm4R_STRCAT
#include <string>
#include <string_view>

namespace mj {

template <typename CharT, typename... Args>
constexpr std::basic_string<CharT> basic_strcat(const Args&... vals)
{
auto len = std::size_t{ 0 };
(len += ... += std::basic_string_view<CharT>{ vals }.length());
auto res = std::basic_string<CharT>{};
res.reserve(len);
(res += ... += vals);
return res;
}

template <typename... Args>
constexpr std::string strcat(const Args&... vals)
{
return basic_strcat<std::string::value_type>(vals...);
}

template <typename... Args>
constexpr std::wstring wcscat(const Args&... vals)
{
return basic_strcat<std::wstring::value_type>(vals...);
}
}

#endif //jm4R_STRCAT
52 changes: 34 additions & 18 deletions include/fast_strcat/string_builder.hpp
Original file line number Diff line number Diff line change
@@ -1,34 +1,50 @@
#include <iostream>
#include <string_view>
#include <tuple>
#ifndef jm4R_STRING_BUILDER
#define jm4R_STRING_BUILDER

#include "strcat.hpp"

#include <string>
#include <tuple>

template<typename... Args>
struct string_builder
{
std::tuple<Args&...> vals;
namespace mj {

template <typename CharT, typename... Args>
struct basic_string_builder {
std::tuple<const Args&...> vals;

template <typename T>
constexpr auto operator<<(T& v) && -> string_builder<Args..., T>
constexpr auto operator<<(const T& v) && -> basic_string_builder<CharT, Args..., T>
{
return {std::tuple_cat(vals, std::tuple<T&>{v})};
return { std::tuple_cat(vals, std::tuple<const T&>{ v }) };
}

constexpr operator std::string() &&
constexpr operator std::basic_string<CharT>() &&
{
auto len = std::size_t{0};
std::apply([&](auto&... x){ (len += ... += std::string_view{x}.length()); } , vals);
return std::apply([&](auto&... vals) { return mj::basic_strcat<CharT>(vals...); }, vals);
}
};

auto res = std::string{};
res.reserve(len);
template <typename... Args>
using string_builder = basic_string_builder<char, Args...>;

std::apply([&](auto&... x){ (res += ... += x); } , vals);
template <typename... Args>
using wstring_builder = basic_string_builder<wchar_t, Args...>;

return res;
}
};
template <typename CharT>
constexpr auto basic_build_string()
{
return basic_string_builder<CharT>{};
}

constexpr auto build_string()
{
return string_builder<>{};
}

constexpr auto build_wstring()
{
return wstring_builder<>{};
}
}

#endif //jm4R_STRING_BUILDER
6 changes: 5 additions & 1 deletion test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ int main()
{
std::string test2 = "test2";
const char* test4 = "test4";
std::string test = build_string() << "test1 " << test2 << " test3 " << test4;
std::string test = mj::build_string() << "test1 " << test2 << " test3 " << test4;
assert(test == "test1 test2 test3 test4");

assert(mj::strcat("a", "b ", test2) == "ab test2");

assert(mj::wcscat(L"a", std::wstring{L"b"}, L"c") == L"abc");
return 0;
}

0 comments on commit dda2c91

Please sign in to comment.