Browse Source

general cleanup

master
Jessica James 3 years ago
parent
commit
6fe7bfb5ac
  1. 48
      src/include/split.hpp

48
src/include/split.hpp

@ -27,44 +27,38 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include "type_traits.hpp" // is_basic_string_view; remove when compilers don't suck
namespace jessilib { namespace jessilib {
namespace impl { namespace impl {
template<typename FirstArgT, typename...> template<template<typename...> typename ContainerT, typename FallbackArg, typename... ArgsT>
struct first_arg { struct split_container_helper {
using first_type = FirstArgT; using type = ContainerT<FallbackArg>;
}; };
// Using a function's return type because both `using` and classes require parameter packs be at the end template<template<typename...> typename ContainerT, typename FallbackArg, typename FirstOptional, typename... ArgsT>
template<template<typename...> typename ContainerT, typename DefaultMemberT, typename... ArgsT, struct split_container_helper<ContainerT, FallbackArg, FirstOptional, ArgsT...> {
typename std::enable_if<sizeof...(ArgsT) == 0>::type* = nullptr> using type = ContainerT<FirstOptional, ArgsT...>;
constexpr auto split_container_helper_f() -> ContainerT<DefaultMemberT> {
return {};
};
template<template<typename...> typename ContainerT, typename DefaultMemberT, typename... ArgsT,
typename std::enable_if<sizeof...(ArgsT) != 0>::type* = nullptr>
constexpr auto split_container_helper_f() -> ContainerT<ArgsT...> {
return {};
}; };
template<template<typename...> typename ContainerT, typename... ArgsT> template<template<typename...> typename ContainerT, typename... ArgsT>
using split_container_helper_t = decltype(split_container_helper_f<ContainerT, ArgsT...>()); using split_container_helper_t = typename split_container_helper<ContainerT, ArgsT...>::type;
template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<is_basic_string_view<MemberT>::value>::type* = nullptr> template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<!std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr>
MemberT member_from_range(ItrT in_itr, EndT in_end) { MemberT member_from_range(ItrT in_itr, EndT in_end) {
// Workaround due to C++20 iterator constructor being inconsistently available // Workaround due to C++20 iterator constructor being inconsistently available
if constexpr (std::is_pointer_v<MemberT>) { if constexpr (std::is_pointer_v<MemberT>) {
return { in_itr, static_cast<size_t>(in_end - in_itr) }; return { in_itr, static_cast<size_t>(in_end - in_itr) };
} }
auto& element = *in_itr; if (in_itr == in_end) {
return { &element, static_cast<size_t>(in_end - in_itr) }; return {};
}
return { &*in_itr, static_cast<size_t>(in_end - in_itr) };
} }
template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<!is_basic_string_view<MemberT>::value>::type* = nullptr> template<typename MemberT, typename ItrT, typename EndT, typename std::enable_if<std::is_constructible<MemberT, ItrT, EndT>::value>::type* = nullptr>
MemberT member_from_range(ItrT in_itr, EndT in_end) { MemberT member_from_range(ItrT in_itr, EndT in_end) {
// Workaround due to C++20 iterator constructor being inconsistently available // Workaround due to C++20 iterator constructor being inconsistently available
return { in_itr, in_end }; return { in_itr, in_end };
@ -84,7 +78,7 @@ MemberT member_from_range(ItrT in_itr, EndT in_end) {
*/ */
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT>
constexpr auto split(ItrT begin, EndT end, ElementT in_delim) { constexpr auto split(ItrT begin, EndT end, ElementT in_delim) {
using MemberT = typename impl::first_arg<ContainerArgsT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>;
container_type result; container_type result;
@ -121,7 +115,7 @@ constexpr auto split(ItrT begin, EndT end, ElementT in_delim) {
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT>
constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) { constexpr auto split(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) {
using ElementT = std::remove_cvref_t<decltype(*begin)>; using ElementT = std::remove_cvref_t<decltype(*begin)>;
using MemberT = typename impl::first_arg<ContainerArgsT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>;
auto delim_length = std::distance(in_delim_begin, in_delim_end); auto delim_length = std::distance(in_delim_begin, in_delim_end);
@ -196,7 +190,7 @@ constexpr auto split(const InputT& in_string, const DelimT& in_delim) {
template<typename... OptionalMemberT, typename ItrT, typename EndT, typename ElementT> template<typename... OptionalMemberT, typename ItrT, typename EndT, typename ElementT>
constexpr auto split_once(ItrT begin, EndT end, ElementT in_delim) { constexpr auto split_once(ItrT begin, EndT end, ElementT in_delim) {
static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT"); static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT");
using MemberT = typename impl::first_arg<OptionalMemberT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<OptionalMemberT..., std::basic_string<ElementT>>>;
std::pair<MemberT, MemberT> result; std::pair<MemberT, MemberT> result;
if (begin >= end) { if (begin >= end) {
@ -235,7 +229,7 @@ template<typename... OptionalMemberT, typename ItrT, typename EndT, typename Del
constexpr auto split_once(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) { constexpr auto split_once(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end) {
static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT"); static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT");
using ElementT = std::remove_cvref_t<decltype(*begin)>; using ElementT = std::remove_cvref_t<decltype(*begin)>;
using MemberT = typename impl::first_arg<OptionalMemberT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<OptionalMemberT..., std::basic_string<ElementT>>>;
auto delim_length = std::distance(in_delim_begin, in_delim_end); auto delim_length = std::distance(in_delim_begin, in_delim_end);
if (delim_length == 1) { if (delim_length == 1) {
@ -286,7 +280,7 @@ template<typename... OptionalMemberT, typename InputT>
constexpr auto split_once(const InputT& in_string, typename InputT::value_type in_delim) { constexpr auto split_once(const InputT& in_string, typename InputT::value_type in_delim) {
static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT"); static_assert(sizeof...(OptionalMemberT) <= 1, "Too many member types specified for OptionalMemberT");
using ElementT = typename InputT::value_type; using ElementT = typename InputT::value_type;
using MemberT = typename impl::first_arg<OptionalMemberT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<OptionalMemberT..., std::basic_string<ElementT>>>;
return split_once<MemberT>(in_string.begin(), in_string.end(), in_delim); return split_once<MemberT>(in_string.begin(), in_string.end(), in_delim);
} }
@ -311,7 +305,7 @@ constexpr auto split_once(const InputT& in_string, const DelimT& in_delim) {
*/ */
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename ElementT>
constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit) { constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit) {
using MemberT = typename impl::first_arg<ContainerArgsT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>;
container_type result; container_type result;
@ -350,7 +344,7 @@ constexpr auto split_n(ItrT begin, EndT end, ElementT in_delim, size_t in_limit)
template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT> template<template<typename...> typename ContainerT = std::vector, typename... ContainerArgsT, typename ItrT, typename EndT, typename DelimItrT, typename DelimEndT>
constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end, size_t in_limit) { constexpr auto split_n(ItrT begin, EndT end, DelimItrT in_delim_begin, DelimEndT in_delim_end, size_t in_limit) {
using ElementT = std::remove_cvref_t<decltype(*begin)>; using ElementT = std::remove_cvref_t<decltype(*begin)>;
using MemberT = typename impl::first_arg<ContainerArgsT..., std::basic_string<ElementT>>::first_type; using MemberT = std::tuple_element_t<0, std::tuple<ContainerArgsT..., std::basic_string<ElementT>>>;
using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>; using container_type = impl::split_container_helper_t<ContainerT, MemberT, ContainerArgsT...>;
auto delim_length = std::distance(in_delim_begin, in_delim_end); auto delim_length = std::distance(in_delim_begin, in_delim_end);

Loading…
Cancel
Save