C++ 在C API中使用gsl::zstring_视图
我正在尝试使用现代的字符串处理方法(如or)与C API(DBus)交互,该API将字符串作为以null结尾的C++ 在C API中使用gsl::zstring_视图,c++,string-view,cpp-core-guidelines,guideline-support-library,string-span,C++,String View,Cpp Core Guidelines,Guideline Support Library,String Span,我正在尝试使用现代的字符串处理方法(如or)与C API(DBus)交互,该API将字符串作为以null结尾的const char*s,例如 DBusMessage* dbus_message_new_method_call( const char* destination, const char* path, const char* iface, const char* method ) string\u view和string\u span不保证它
const char*
s,例如
DBusMessage* dbus_message_new_method_call(
const char* destination,
const char* path,
const char* iface,
const char* method
)
string\u view
和string\u span
不保证它们的内容以null结尾-因为span是(char*start,ptrdiff\t length)
对,这在很大程度上是关键。但GSL还提供了一个zstring_视图
,它保证以null结尾。周围的zstring_span
表明它的设计完全是为了处理遗留API和C API,但我一开始使用它就遇到了几个问题:
string\u span
很简单:
cstring_span<> bar = "easy peasy";
这使得声明更加嘈杂,而且文字(保证以null结尾)不能隐式转换为zstring\u span
,这似乎也很奇怪确保_z()
与字符串span
的构造函数和转换不同,也不是constexpr
std::string
也有类似的奇怪之处,它可以隐式转换为string\u span
,但不能转换为zstring\u span
,即使std::string::data()。同样,您必须调用确保_z()
:
zstring_span to_zspan(std::string&s){return sure_z(s)}
czstring_span<> to_czspan(const std::string& s) { return ensure_z(s); }
czstring_span to_czspan(const std::string&s){return sure_z(s)}
编译失败,错误是无法从span
转换为span
char*
(您可以将其馈送到像DBus这样的C API)的成员函数称为aspect_z()
。当zstring\u span的构造函数
zstring_span
被设计为“将以零结尾的跨距转换为传统的字符串”,为什么它在这里的使用看起来如此繁琐?我是不是误用了?有什么东西我忽略了吗?它之所以“笨重”,部分是因为它是有意忽略的
这:
zstring_span to_zspan(std::string&s){return sure_z(s)}
这不是一个安全的操作。为什么?因为虽然s
确实以NUL结尾,但实际的s
完全可能包含内部NUL字符。这是你可以用std::string
做的合法的事情,但是zstring\u span
任何人都无法处理。他们将截断字符串
相反,从这个角度来看,string\u span/view
转换是安全的。这类字符串的使用者使用大小相同的字符串,因此可以处理嵌入式NUL
因为zstring_span
转换是不安全的,所以应该有一些明确的标记,表明正在进行一些可能不安全的操作<代码>确保_z表示该显式符号
另一个问题是C++没有机制来区分文字字符串参数和任何旧的代码> const char */COD>或<代码> const char []/COD>参数。由于裸
常量char*
可能是也可能不是字符串文字,因此必须假设它不是,因此使用更详细的转换
C++中的字符串文字也可以包含嵌入的NUL字符,因此适用上述推理。
const
问题似乎是一个代码错误,您可能应该将其归档
zstring\u span
常量字符[…]
。类型中没有信息表明此const char
数组是以null结尾的字符串。下面是一些具有相同类型的其他代码,但没有空终止,其中确保_z
将快速失败
const char foo_arr[4]{ 'o', 'd', 'd', '-' };
ensure_z(foo_arr);
“foo”
和foo_arr
都属于const char[4]
类型,但只有字符串文字以null结尾,而foo_arr
则不是
请注意,sure_z
和czstring_span
的组合可以编译,但不起作用<代码>确保_z只返回字符串,不返回终止的空字节。当您将其传递给czstring\u span
构造函数时,构造函数将无法搜索空字节(该字节被sure\u z
截断)
您需要将字符串文字转换为跨度,并将其传递给构造函数:
czstring_span<> foo = ensure_span("odd");
你应该考虑在GSL回购协议中提交一个问题,使各阶层保持一致。我不确定隐式转换是否是个好主意,因此我更喜欢在zstring\u span
中如何进行隐式转换,而不是string\u span
如何进行隐式转换
czstring\u span to_czspan(const std::string&s){return czstring\u span{s};}
编译了,但不起作用。另一个解决方案是一个新函数sure_cz
,它返回span
。你应该考虑提交一个问题。
假设_z()
empty()
的存在和中的代码as\u string\u span()
表明类应该能够处理空字符串跨度。在这种情况下,由于_string_span
总是返回字符串而不终止空字节,确保_z
将返回带有终止空字节的字符串,如果为空则失败,假设_z
将假设!empty()
并返回带有终止空字节的字符串
但是唯一的构造函数使用非空的字符跨度,因此empty()
永远不能zstring_span<> to_zspan(std::string& s) { return ensure_z(s); }
const char foo_arr[4]{ 'o', 'd', 'd', '-' };
ensure_z(foo_arr);
czstring_span<> foo = ensure_span("odd");
zstring_span<> to_zspan(std::string& s) { return zstring_span<>{s}; }