trim_left 使用 string_view 禁止临时参数的实现
trim_left implementation using string_view disallowing temporary parameters
我想实现一个非拷贝数据trim_left的功能,但是不想让它接受临时参数,让返回的string_view有效(数据还在活)。
我开始接受 string_view 作为参数,但我不知道如何保证数据有效。
所以我做了这个:
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;
我对第二个删除模板的想法是禁止使用临时对象作为参数并保证返回的 string_view 有效。
我希望这是有效的:
auto sv1 = trim_left("ABCHello" , "ABC");
string data = "ABCHello";
auto sv2 = trim_left( data, "ABC");
但不是这个...
string fee( return "ABCHello"; );
auto sv3 = trim_left( fee(), "ABC");
这是正确的做法吗?
是否可以通过在第一个模板上设置 enable_if 参数而不使用第二个模板来做到这一点?
测试实现:https://wandbox.org/permlink/7q3cLGbGrX9b6q5S
谢谢!!
嗯...鉴于 trim_left()
没有改变 data
,我想你可以写主 trim_left()
接收 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;
}
然后你可以添加一个辅助trim_left()
接收一个T &
并调用主版本添加const
到data
template <typename T>
std::string_view trim_left (T & data, std::string_view tc)
{ return trim_left((T const &)data, tc); }
最后一个已删除trim_left()
供大家参考
template <typename T>
std::string_view trim_left (T &&, std::string_view) = delete;
现在你有
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
我找到了第二个实现:
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;
}
测试用例:https://wandbox.org/permlink/ZOaO4NDI28yQHXy9
我觉得比第一个简单,也可以通过测试。看来这就是我要找的。
我想实现一个非拷贝数据trim_left的功能,但是不想让它接受临时参数,让返回的string_view有效(数据还在活)。 我开始接受 string_view 作为参数,但我不知道如何保证数据有效。
所以我做了这个:
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;
我对第二个删除模板的想法是禁止使用临时对象作为参数并保证返回的 string_view 有效。
我希望这是有效的:
auto sv1 = trim_left("ABCHello" , "ABC");
string data = "ABCHello";
auto sv2 = trim_left( data, "ABC");
但不是这个...
string fee( return "ABCHello"; );
auto sv3 = trim_left( fee(), "ABC");
这是正确的做法吗? 是否可以通过在第一个模板上设置 enable_if 参数而不使用第二个模板来做到这一点?
测试实现:https://wandbox.org/permlink/7q3cLGbGrX9b6q5S
谢谢!!
嗯...鉴于 trim_left()
没有改变 data
,我想你可以写主 trim_left()
接收 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;
}
然后你可以添加一个辅助trim_left()
接收一个T &
并调用主版本添加const
到data
template <typename T>
std::string_view trim_left (T & data, std::string_view tc)
{ return trim_left((T const &)data, tc); }
最后一个已删除trim_left()
供大家参考
template <typename T>
std::string_view trim_left (T &&, std::string_view) = delete;
现在你有
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
我找到了第二个实现:
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;
}
测试用例:https://wandbox.org/permlink/ZOaO4NDI28yQHXy9
我觉得比第一个简单,也可以通过测试。看来这就是我要找的。