I'd like to implement a non-copy data trim_left function, but would like to not allow it to accept temporary parameters to make the returned string_view is valid (the data is still alive). I started accepting string_view as parameter, but I cannot get the way how to guarantee the data is valid.
So I make this:
template<typename T>
std::string_view trim_left( const T& data, std::string_view trimChars )
{
std::string_view sv{data};
sv.remove_prefix( std::min(sv.find_first_not_of(trimChars), sv.size()));
return sv;
}
template<typename T, std::enable_if_t< !std::is_same<std::decay_t<T>,std::string_view>::value , int > = 0>
std::string_view trim_left( const T&& data, std::string_view trimChars ) = delete;
My idea with the second deleted template is to disable the use of temporary object as parameters and guarantee the returned string_view is valid.
I expect that this is valid:
auto sv1 = trim_left("ABCHello" , "ABC");
string data = "ABCHello";
auto sv2 = trim_left( data, "ABC");
but not this...
string fee( return "ABCHello"; );
auto sv3 = trim_left( fee(), "ABC");
Is this the proper way to do it? Is it possible to do this by setting a enable_if parameter on the first template and not use the second one?
Test implementation: https://wandbox.org/permlink/7q3cLGbGrX9b6q5S
Thanks!!
Well... given that trim_left()
doesn't change data
, I suppose that you can write the main trim_left()
receiving a T const &
template <typename T>
std::string_view trim_left (T const & data, std::string_view trimChars)
{
std::string_view sv{data};
sv.remove_prefix( std::min(sv.find_first_not_of(trimChars), sv.size()));
return sv;
}
Then you can add an auxiliary trim_left()
that receive a T &
and call the main version adding const
to data
template <typename T>
std::string_view trim_left (T & data, std::string_view tc)
{ return trim_left((T const &)data, tc); }
Last a deleted trim_left()
for universal reference
template <typename T>
std::string_view trim_left (T &&, std::string_view) = delete;
Now you have
auto sv1 = trim_left("ABCHello" , "ABC"); // OK: main version (const &)
std::string data = "ABCHello";
auto sv2 = trim_left( data, "ABC"); // OK: auxiliary version (&)
// auto sv3 = trim_left( fee(), "ABC"); // compiler error: deleted version
I find out this second implementation:
template<typename T, std::enable_if_t< std::is_same<T, std::string_view>::value || !std::is_rvalue_reference_v<T&&>, int > = 0 >
std::string_view trim_left( T&& data, std::string_view trimChars )
{
std::string_view sv{std::forward<T>(data)};
sv.remove_prefix( std::min(sv.find_first_not_of(trimChars), sv.size()));
return sv;
}
Test case: https://wandbox.org/permlink/ZOaO4NDI28yQHXy9
I think is simple than the first one, and also works with the tests. Seems it's what I was looking for.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.