Skip to content

Instantly share code, notes, and snippets.

@SaitoAtsushi
Created September 6, 2022 02:36
Show Gist options
  • Save SaitoAtsushi/3eabfe695f29a89e6afb7f1da9d8eafa to your computer and use it in GitHub Desktop.
Save SaitoAtsushi/3eabfe695f29a89e6afb7f1da9d8eafa to your computer and use it in GitHub Desktop.
文字列の連結
#include <algorithm>
#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
template <class T, class = void>
class is_string : public std::false_type {};
template <class T>
struct is_string<T, std::void_t<decltype(std::basic_string_view<typename T::value_type>(std::declval<T>()))>> : public std::true_type {};
template <class T>
struct is_string<T *, std::void_t<decltype(std::basic_string_view<T>(std::declval<T *>()))>> : public std::true_type {};
template <class T>
inline constexpr bool is_string_v = is_string<std::decay_t<T>>::value;
template <class T, class U = void>
struct string_element {
static_assert(!sizeof(T), "Expected string-like type.");
};
template <class T>
struct string_element<T, std::void_t<decltype(std::basic_string_view<typename T::value_type>(std::declval<T>()))>> {
using type = typename std::basic_string_view<typename T::value_type>::value_type;
};
template <class T>
struct string_element<T *, std::void_t<decltype(std::basic_string_view<T>(std::declval<T *>()))>> {
using type = typename std::basic_string_view<T>::value_type;
};
template <class T>
using string_element_t = typename string_element<std::decay_t<T>>::type;
template <class T, class... U>
inline constexpr bool is_all_same_v = (std::is_same_v<T, U> && ...);
template <class T, class... U>
auto string_append(const T &head, const U &...tail)
-> std::enable_if_t<is_all_same_v<std::decay_t<T>, std::decay_t<U>...> && is_string_v<T>, std::basic_string<string_element_t<T>>> {
using char_type = string_element_t<T>;
auto input_strings = std::initializer_list<const std::basic_string_view<char_type>>{head, tail...};
std::basic_string<char_type> result;
for (auto &x : input_strings) std::copy(std::begin(x), std::end(x), std::back_inserter(result));
return result;
}
int main(void) {
// char* 同士の連結
const std::string foo = string_append("abc", "defg", "hi");
std::cout << foo << std::endl;
// wchar_t* 同士の連結
const std::wstring bar = string_append(L"1", L"2345", L"678");
std::wcout << bar << std::endl;
// std::string 同士の連結
const std::string baz = string_append(foo, foo);
std::cout << baz << std::endl;
// std::wstring 同士の連結
const std::wstring qux = string_append(bar, bar);
std::wcout << qux << std::endl;
// その他の型の文字列の連結
const std::u16string quux = string_append(u"あ", u"いう", u"えお");
std::u32string corge = string_append(U"いろ", U"はにほ", U"へと");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment