From cc63c8c250db6c9fffd84d367f1939ff00ea6c4a Mon Sep 17 00:00:00 2001 From: Martchus Date: Fri, 5 Mar 2021 23:01:30 +0100 Subject: [PATCH] Improve parameter-passing in some string conversion functions * Allow using a range as input of joinStrings() * Use `std::string_view` instead of `const std::string &` to pass read-only parameters to joinStrings() and splitString*() to avoid constructing an `std::string` from `const char *` parameters * Use auto for return types of toMultiline() and toArrayOfLines() * Does not affect BC because those are template functions * Should not affect source compatibility; at least uses in my main projects seem to be unaffected --- conversion/stringconversion.h | 37 ++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/conversion/stringconversion.h b/conversion/stringconversion.h index b50f704..af77105 100644 --- a/conversion/stringconversion.h +++ b/conversion/stringconversion.h @@ -18,6 +18,10 @@ #include #include +#if __cplusplus >= 201709 +#include +#endif + namespace CppUtilities { /*! @@ -59,6 +63,20 @@ CPP_UTILITIES_EXPORT WideStringData convertMultiByteToWide(const std::string &in CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar = '\0'); +/// \cond +namespace Detail { +#if __cplusplus >= 201709 +template +using ContainerValueType = typename std::conditional_t, + std::iterator_traits>>, Container>::value_type; +#else +template using ContainerValueType = typename Container::value_type; +#endif +template using DefaultReturnTypeForContainer = ContainerValueType; +template using StringParamForContainer = std::basic_string_view::value_type>; +} // namespace Detail +/// \endcond + /*! * \brief Joins the given \a strings using the specified \a delimiter. * @@ -69,13 +87,14 @@ CPP_UTILITIES_EXPORT void truncateString(std::string &str, char terminationChar * \param omitEmpty Indicates whether empty part should be omitted. * \param leftClosure Specifies a string to be inserted before each string (empty string by default). * \param rightClosure Specifies a string to be appendend after each string (empty string by default). - * \tparam Container The STL-container used to provide the \a strings. + * \tparam Container Container The STL-container used to provide the \a strings. + * \tparam ReturnType Type to store the result; defaults to the container's element type. * \returns Returns the joined string. */ -template , class ReturnType = typename Container::value_type> -ReturnType joinStrings(const Container &strings, const typename Container::value_type &delimiter = typename Container::value_type(), - bool omitEmpty = false, const typename Container::value_type &leftClosure = typename Container::value_type(), - const typename Container::value_type &rightClosure = typename Container::value_type()) +template , class ReturnType = Detail::DefaultReturnTypeForContainer> +ReturnType joinStrings(const Container &strings, Detail::StringParamForContainer delimiter = Detail::StringParamForContainer(), + bool omitEmpty = false, Detail::StringParamForContainer leftClosure = Detail::StringParamForContainer(), + Detail::StringParamForContainer rightClosure = Detail::StringParamForContainer()) { ReturnType res; if (!strings.size()) { @@ -111,7 +130,7 @@ ReturnType joinStrings(const Container &strings, const typename Container::value /*! * \brief Converts the specified \a arrayOfLines to a multiline string. */ -template > inline std::vector toMultiline(const Container &arrayOfLines) +template > inline auto toMultiline(const Container &arrayOfLines) { return joinStrings(arrayOfLines, "\n", false); } @@ -135,7 +154,7 @@ enum class EmptyPartsTreat { * \returns Returns the parts. */ template > -Container splitString(const typename Container::value_type &string, const typename Container::value_type &delimiter, +Container splitString(Detail::StringParamForContainer string, Detail::StringParamForContainer delimiter, EmptyPartsTreat emptyPartsRole = EmptyPartsTreat::Keep, int maxParts = -1) { --maxParts; @@ -183,7 +202,7 @@ Container splitString(const typename Container::value_type &string, const typena * \remarks This is a simplified version of splitString() where emptyPartsRole is always EmptyPartsTreat::Keep. */ template > -Container splitStringSimple(const typename Container::value_type &string, const typename Container::value_type &delimiter, int maxParts = -1) +Container splitStringSimple(Detail::StringParamForContainer string, Detail::StringParamForContainer delimiter, int maxParts = -1) { --maxParts; Container res; @@ -211,7 +230,7 @@ Container splitStringSimple(const typename Container::value_type &string, const /*! * \brief Converts the specified \a multilineString to an array of lines. */ -template > inline std::vector toArrayOfLines(const std::string &multilineString) +template > inline auto toArrayOfLines(const std::string &multilineString) { return splitString(multilineString, "\n", EmptyPartsTreat::Keep); }