Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify str_arg_char template specialization #77

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 31 additions & 55 deletions include/upa/str_arg.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
/**************************************************************
// Usage example:

template <class ...Args, enable_if_str_arg_t<Args...> = 0>
inline void procfn(Args&&... args) {
const auto inp = make_str_arg(std::forward<Args>(args)...);
template <class StrT, enable_if_str_arg_t<StrT> = 0>
inline void procfn(StrT&& str) {
const auto inp = make_str_arg(std::forward<StrT>(str));
const auto* first = inp.begin();
const auto* last = inp.end();
// do something with first ... last
Expand Down Expand Up @@ -76,18 +76,17 @@ class str_arg {
: first_(s)
, last_(s + traits_type::length(s))
{}
str_arg(const CharT* s, std::size_t length)
: first_(s)
, last_(s + length)
{}
str_arg(const CharT* s, std::ptrdiff_t length)

template <typename SizeT, std::enable_if_t<is_size_type_v<SizeT>, int> = 0>
str_arg(const CharT* s, SizeT length)
: first_(s)
, last_(s + length)
{}
{ assert(length >= 0); }

str_arg(const CharT* first, const CharT* last)
: first_(first)
, last_(last)
{}
{ assert(first <= last); }

// destructor
~str_arg() noexcept = default;
Expand Down Expand Up @@ -150,33 +149,10 @@ namespace detail {

// Requirements for string arguments

template<class ...Args>
template<class StrT, typename = void>
struct str_arg_char {};

// two pointers
template<class CharT>
struct str_arg_char<CharT*, CharT*> : std::remove_cv<CharT> {

template <typename T>
static str_arg<T> to_str_arg(const T* first, const T* last) {
assert(first <= last);
return { first, last };
}
};

// pointer and size
template<class CharT, class SizeT>
struct str_arg_char<CharT*, SizeT> : std::enable_if<
is_size_type_v<SizeT>,
std::remove_cv_t<CharT>> {

template <typename T>
static str_arg<T> to_str_arg(const T* s, std::size_t length) {
return { s, length };
}
};

// one pointer (null terminated string)
// Null terminated string
template<class CharT>
struct str_arg_char<CharT*> : std::remove_cv<CharT> {

Expand All @@ -186,7 +162,7 @@ struct str_arg_char<CharT*> : std::remove_cv<CharT> {
}
};

// one string class argument
// String that has data() and length() members
template<class StrT>
struct str_arg_char<StrT> : std::enable_if<
std::is_pointer_v<detail::data_member_t<StrT>> &&
Expand All @@ -202,24 +178,24 @@ struct str_arg_char<StrT> : std::enable_if<

// String arguments helper types

template<class ...Args>
using str_arg_char_s = str_arg_char<std::decay_t<Args>...>;
template<class StrT>
using str_arg_char_s = str_arg_char<std::decay_t<StrT>>;

template<class ...Args>
using str_arg_char_t = typename str_arg_char_s<Args...>::type;
template<class StrT>
using str_arg_char_t = typename str_arg_char_s<StrT>::type;


template<class ...Args>
template<class StrT>
using enable_if_str_arg_t = std::enable_if_t<
is_char_type_v<str_arg_char_t<Args...>>,
is_char_type_v<str_arg_char_t<StrT>>,
int>;


// String arguments helper function

template <class ...Args>
inline auto make_str_arg(Args&&... args) -> str_arg<str_arg_char_t<Args...>> {
return str_arg_char_s<Args...>::to_str_arg(std::forward<Args>(args)...);
template <class StrT>
inline auto make_str_arg(StrT&& str) -> str_arg<str_arg_char_t<StrT>> {
return str_arg_char_s<StrT>::to_str_arg(std::forward<StrT>(str));
}


Expand All @@ -233,9 +209,9 @@ constexpr bool is_char8_type_v =
#endif
;

template<class ...Args>
template<class StrT>
using enable_if_str_arg_to_char8_t = std::enable_if_t<
is_char8_type_v<str_arg_char_t<Args...>>,
is_char8_type_v<str_arg_char_t<StrT>>,
int>;

template<class CharT>
Expand All @@ -244,25 +220,25 @@ constexpr bool is_charW_type_v =
std::is_same_v<CharT, char32_t> ||
std::is_same_v<CharT, wchar_t>;

template<class ...Args>
template<class StrT>
using enable_if_str_arg_to_charW_t = std::enable_if_t<
is_charW_type_v<str_arg_char_t<Args...>>,
is_charW_type_v<str_arg_char_t<StrT>>,
int>;


inline std::string&& make_string(std::string&& str) {
return std::move(str);
}

template <class ...Args, enable_if_str_arg_to_char8_t<Args...> = 0>
inline string_view make_string(Args&&... args) {
const auto inp = make_str_arg(std::forward<Args>(args)...);
template <class StrT, enable_if_str_arg_to_char8_t<StrT> = 0>
inline string_view make_string(StrT&& str) {
const auto inp = make_str_arg(std::forward<StrT>(str));
return { inp.data(), inp.length() };
}

template <class ...Args, enable_if_str_arg_to_charW_t<Args...> = 0>
inline std::string make_string(Args&&... args) {
const auto inp = make_str_arg(std::forward<Args>(args)...);
template <class StrT, enable_if_str_arg_to_charW_t<StrT> = 0>
inline std::string make_string(StrT&& str) {
const auto inp = make_str_arg(std::forward<StrT>(str));
return url_utf::to_utf8_string(inp.begin(), inp.end());
}

Expand Down
2 changes: 1 addition & 1 deletion include/upa/url_for_atl.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct str_arg_char_for_atl {
using type = typename StrT::XCHAR;

static str_arg<type> to_str_arg(const StrT& str) {
return { str.GetString(), static_cast<std::ptrdiff_t>(str.GetLength()) };
return { str.GetString(), str.GetLength() };
}
};

Expand Down
6 changes: 1 addition & 5 deletions include/upa/url_for_qt.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# include <QUtf8StringView>
#endif
#include <cstddef> // std::ptrdiff_t

namespace upa {

Expand All @@ -33,10 +32,7 @@ struct str_arg_char_for_qt {
using type = CharT;

static str_arg<type> to_str_arg(const StrT& str) {
return {
reinterpret_cast<const type*>(str.data()),
static_cast<std::ptrdiff_t>(str.length())
};
return { reinterpret_cast<const type*>(str.data()), str.length() };
}
};

Expand Down
51 changes: 26 additions & 25 deletions test/test-str_arg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@

// Function to test

using namespace upa;

template <class ...Args, enable_if_str_arg_t<Args...> = 0>
inline std::size_t procfn(Args&&... args) {
const auto inp = make_str_arg(std::forward<Args>(args)...);
template <class StrT, upa::enable_if_str_arg_t<StrT> = 0>
inline std::size_t procfn(StrT&& str) {
const auto inp = upa::make_str_arg(std::forward<StrT>(str));
return std::distance(inp.begin(), inp.end());
}

Expand Down Expand Up @@ -54,7 +52,7 @@ struct str_arg_char<CustomString<CharT>> {

template <class CharT>
inline void test_char() {
const size_t N = 3;
const std::size_t N = 3;
CharT arr[] = { '1', '2', '3', 0 };
const CharT carr[] = { '1', '2', '3', 0 };
CharT* ptr = arr;
Expand All @@ -67,30 +65,33 @@ inline void test_char() {
procfn(cptr);
procfn(vptr);

procfn(arr, N);
procfn(carr, N);
procfn(ptr, N);
procfn(cptr, N);
procfn(vptr, N);

// upa::str_arg
upa::str_arg<CharT> arg{ arr };
procfn(arg);
const upa::str_arg carg{ arr };
procfn(carg);

procfn(upa::str_arg{ arr, N });
procfn(upa::str_arg{ carr, N });
procfn(upa::str_arg{ ptr, N });
procfn(upa::str_arg{ cptr, N });
procfn(upa::str_arg{ vptr, N });
// int size
procfn(arr, int(N));
procfn(cptr, int(N));
procfn(upa::str_arg{ arr, static_cast<int>(N) });
procfn(upa::str_arg{ cptr, static_cast<int>(N) });

procfn(arr, arr + N);
procfn(carr, carr + N);
procfn(ptr, ptr + N);
procfn(cptr, cptr + N);
procfn(vptr, vptr + N);
procfn(upa::str_arg{ arr, arr + N });
procfn(upa::str_arg{ carr, carr + N });
procfn(upa::str_arg{ ptr, ptr + N });
procfn(upa::str_arg{ cptr, cptr + N });
procfn(upa::str_arg{ vptr, vptr + N });

const std::basic_string<CharT> str(arr);
// std::basic_string
const std::basic_string<CharT> str{ arr };
procfn(str);
procfn(std::basic_string<CharT>(arr));

upa::str_arg<CharT> arg(arr);
procfn(arg);
procfn(std::basic_string<CharT>{ arr });

// test custom string
// custom string
procfn(CustomString<CharT>{cptr, N});
}

Expand Down