Skip to content

Commit

Permalink
Simplify str_arg_char template specialization
Browse files Browse the repository at this point in the history
* One string class parameter is used instead of the parameter pack

* Simplified use of the str_arg constructor with string pointer and
  length parameters - length can now be any integer.
  • Loading branch information
rmisev committed Nov 7, 2024
1 parent 84e8772 commit 35d2441
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 84 deletions.
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 @@ -86,18 +86,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, typename std::enable_if<is_size_type<SizeT>::value, int>::type = 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 @@ -160,33 +159,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<SizeT>::value,
typename std::remove_cv<CharT>::type> {

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 @@ -196,7 +172,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<detail::data_member_t<StrT>>::value &&
Expand All @@ -212,24 +188,24 @@ struct str_arg_char<StrT> : std::enable_if<

// String arguments helper types

template<class ...Args>
using str_arg_char_s = str_arg_char<typename std::decay<Args>::type...>;
template<class StrT>
using str_arg_char_s = str_arg_char<typename std::decay<StrT>::type>;

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 = typename std::enable_if<
is_char_type<str_arg_char_t<Args...>>::value,
is_char_type<str_arg_char_t<StrT>>::value,
int>::type;


// 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 @@ -243,9 +219,9 @@ struct is_char8_type : std::integral_constant<bool,
#endif
> {};

template<class ...Args>
template<class StrT>
using enable_if_str_arg_to_char8_t = typename std::enable_if<
is_char8_type<str_arg_char_t<Args...>>::value,
is_char8_type<str_arg_char_t<StrT>>::value,
int>::type;

template<class CharT>
Expand All @@ -255,25 +231,25 @@ struct is_charW_type : std::integral_constant<bool,
std::is_same<CharT, wchar_t>::value
> {};

template<class ...Args>
template<class StrT>
using enable_if_str_arg_to_charW_t = typename std::enable_if<
is_charW_type<str_arg_char_t<Args...>>::value,
is_charW_type<str_arg_char_t<StrT>>::value,
int>::type;


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 @@ -25,7 +25,6 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# include <QUtf8StringView>
#endif
#include <cstddef> // std::ptrdiff_t

namespace upa {

Expand All @@ -36,10 +35,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
47 changes: 24 additions & 23 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<CharT> carg(arr);
procfn(carg);

procfn(upa::str_arg<CharT>{arr, N});
procfn(upa::str_arg<CharT>{carr, N});
procfn(upa::str_arg<CharT>{ptr, N});
procfn(upa::str_arg<CharT>{cptr, N});
procfn(upa::str_arg<CharT>{vptr, N});
// int size
procfn(arr, int(N));
procfn(cptr, int(N));
procfn(upa::str_arg<CharT>(arr, static_cast<int>(N)));
procfn(upa::str_arg<CharT>(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<CharT>{arr, arr + N});
procfn(upa::str_arg<CharT>{carr, carr + N});
procfn(upa::str_arg<CharT>{ptr, ptr + N});
procfn(upa::str_arg<CharT>{cptr, cptr + N});
procfn(upa::str_arg<CharT>{vptr, vptr + N});

// 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);

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

Expand Down

0 comments on commit 35d2441

Please sign in to comment.