简体   繁体   中英

trim_left implementation using string_view disallowing temporary parameters

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM