有自由功能路线,但是除非您也提供过载,std::string
否则这是一个蛇坑。
#include <string>
#include <string_view>
std::string_view sub_string(
std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
auto bar = sub_string(source, 3);
bar = sub_string("foobar"s, 3);
}
恕我直言,string_view的整个设计是一个恐怖的表演,它将带我们回到一个充满争议和愤怒的客户的世界。
更新:
甚至添加超载std::string
也是恐怖的表演。看看您是否能发现微妙的段错误定时炸弹...
#include <string>
#include <string_view>
std::string_view sub_string(std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string&& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string const& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
auto bar = sub_string(std::string_view(source), 3);
bar = sub_string("foobar"s, 3);
}
编译器在这里没有发现任何警告。我敢肯定,代码审查也不会。
我已经说过了,再说一遍,以防c ++委员会上的任何人在看,允许从std::string
到的隐式转换std::string_view
是一个可怕的错误,只会使c ++蒙羞。
更新资料
在cpporg留言板上提出了string_view的这个(对我来说)相当令人震惊的属性后,我的关心变得冷漠。
该小组的建议的共识是,std::string_view
绝不能从函数中返回它,这意味着我上面的第一个提议是错误的形式。
当然,如果偶然发生(例如通过模板扩展),则没有编译器帮助来捕获时间。
因此,std::string_view
应格外小心,因为从内存管理的角度来看,它等效于指向另一个对象状态的可复制指针,该对象可能不再存在。但是,它在所有其他方面的外观和行为都类似于值类型。
因此,代码如下:
auto s = get_something().get_suffix();
get_suffix()
返回std::string
(按值或引用)时是安全的
但如果将get_suffix()重构为返回a,则为UB std::string_view
。
在我的拙劣观点中,这意味着auto
如果将他们调用的库重构为std::string_view
代替的返回值,则使用返回的字符串存储的任何用户代码都将中断std::string const&
。
因此,从现在开始,至少对于我来说,“几乎总是自动的”必须变成“几乎总是自动的,除非是字符串”。
string_view(s).substr(...)
)似乎比单个函数同时执行两项操作()更好,.substr_view(...)
即使它确实存在。