如何将 std::string_view 转换为 const char*?
How you convert a std::string_view to a const char*?
使用带有标志 -std=c++17
的 gcc-7.1 编译,以下程序会引发错误:
#include <string_view>
void foo(const char* cstr) {}
void bar(std::string_view str){
foo(str);
}
错误信息是
In function 'void bar(std::string_view)':
error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)'
foo(str);
我很惊讶没有转换为 const char*
,因为其他库(abseil、bde)提供类似的 string_view
类,它隐式转换为 const char*
。
A std::string_view
不提供到 const char*
的转换,因为 它不存储以 null 结尾的字符串。它基本上存储指向第一个元素的指针和字符串的长度。这意味着您不能将它传递给期望以 null 结尾的字符串的函数,例如 foo
(否则您将如何获得大小?)期望 const char*
,因此决定这不值得。
如果您确定您的视图中有一个以 null 结尾的字符串,您可以使用 std::string_view::data
.
如果你不是,你应该重新考虑首先使用 std::string_view
是否是一个好主意,因为如果你想要一个有保证的以 null 结尾的字符串 std::string
就是你想要的。对于单行,您可以使用 std::string(object).data()
(注意:return 值指向 临时 std::string
表达式结束后将被销毁的实例!)。
您可以拨打foo(std::string(str).c_str())
.
只需执行 std::string(string_view_object).c_str()
即可获得有保证的以 null 结尾的临时副本(并在行尾清理它)。
这是必需的,因为字符串视图不保证空终止。例如,您可以查看较长缓冲区的中间。
如果这个用例很昂贵并且你已经证明它是一个瓶颈,你可以编写一个增强的 string_view
来跟踪它是否以 null 终止(基本上,如果它是从原始 char const*
).
然后你可以编写一个辅助类型,它接受这个扩充的 string_view
并将它复制到 std::string
或直接存储扩充的 string_view
,并且有一个隐式转换-char const*
returns 正确的空终止缓冲区。
然后在你的代码库中到处使用那个增强的帮助器类型而不是 string_view
,可能会增加字符串视图与 std 字符串的交互,以及捕捉你有一个视图结束的情况标准字符串缓冲区。
但实际上,这可能有点矫枉过正。
更好的方法可能是重写需要 const char*
的 API 以使用 string_view
.
使用带有标志 -std=c++17
的 gcc-7.1 编译,以下程序会引发错误:
#include <string_view>
void foo(const char* cstr) {}
void bar(std::string_view str){
foo(str);
}
错误信息是
In function 'void bar(std::string_view)':
error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)'
foo(str);
我很惊讶没有转换为 const char*
,因为其他库(abseil、bde)提供类似的 string_view
类,它隐式转换为 const char*
。
A std::string_view
不提供到 const char*
的转换,因为 它不存储以 null 结尾的字符串。它基本上存储指向第一个元素的指针和字符串的长度。这意味着您不能将它传递给期望以 null 结尾的字符串的函数,例如 foo
(否则您将如何获得大小?)期望 const char*
,因此决定这不值得。
如果您确定您的视图中有一个以 null 结尾的字符串,您可以使用 std::string_view::data
.
如果你不是,你应该重新考虑首先使用 std::string_view
是否是一个好主意,因为如果你想要一个有保证的以 null 结尾的字符串 std::string
就是你想要的。对于单行,您可以使用 std::string(object).data()
(注意:return 值指向 临时 std::string
表达式结束后将被销毁的实例!)。
您可以拨打foo(std::string(str).c_str())
.
只需执行 std::string(string_view_object).c_str()
即可获得有保证的以 null 结尾的临时副本(并在行尾清理它)。
这是必需的,因为字符串视图不保证空终止。例如,您可以查看较长缓冲区的中间。
如果这个用例很昂贵并且你已经证明它是一个瓶颈,你可以编写一个增强的 string_view
来跟踪它是否以 null 终止(基本上,如果它是从原始 char const*
).
然后你可以编写一个辅助类型,它接受这个扩充的 string_view
并将它复制到 std::string
或直接存储扩充的 string_view
,并且有一个隐式转换-char const*
returns 正确的空终止缓冲区。
然后在你的代码库中到处使用那个增强的帮助器类型而不是 string_view
,可能会增加字符串视图与 std 字符串的交互,以及捕捉你有一个视图结束的情况标准字符串缓冲区。
但实际上,这可能有点矫枉过正。
更好的方法可能是重写需要 const char*
的 API 以使用 string_view
.