有没有办法编写 BSTR 文字?
Is there a way to write a BSTR literal?
当调用需要 BSTR 的函数时,最好能够编写如下内容:
iFoo->function( bs"HELLO" );
然而,我知道的唯一解决方法是使用调用 SysAllocString
等的包装器,例如:
iFoo->function( WideString(L"HELLO").c_bstr() );
有点丑。实际上是否有创建 BSTR
文字的选项?
动机:更易于阅读的代码,以及通过避免分配和释放来提高运行时性能。
澄清:我只是在谈论调用者(即我们)拥有 BSTR 所有权的情况,例如:调用一个接受 BSTR [in]
的函数范围。当然,向将继续尝试释放字符串的函数提供指向 BSTR 文字的指针是愚蠢的。
用户定义的文字将是可行的方法:
"HELLO"_bstr
调用 template<char...> BSTR operator "" _bstr ( const char*, std::size_t)
然后可以调用 SysAllocString()
VS14 中的新功能。
[编辑]
根据评论,return 一个 _bstr_t
或其他 class 可能更好,它拥有 SysAllocString()
结果的所有权并隐式转换为 BSTR
。这个临时文件将在完整表达式的末尾被销毁,因此 after iFoo->function( "HELLO"_bstr );
returns.
为了跟进@MSalters 的回答,自定义的用户定义文字可能如下所示:
CComBSTR operator "" _bstr (const char* str, std::size_t len)
{
return CComBSTR(len, str);
}
然后你可以这样做(因为 CComBSTR
定义了 BSTR
转换运算符):
iFoo->function( "HELLO"_bstr );
您甚至可以为多个输入字符串文字类型重载运算符:
CComBSTR operator "" _bstr (const wchar_t* str, std::size_t len)
{
return CComBSTR(len, str);
}
CComBSTR operator "" _bstr (const char16_t* str, std::size_t len)
{
return CComBSTR(len, (wchar_t*)str);
}
iFoo->function( L"HELLO"_bstr ); // calls wchar_t* version with UTF-16 encoded data
iFoo->function( u"HELLO"_bstr ); // calls char16_t* version with UTF-16 encoded data
iFoo->function( u8"HELLO"_bstr ); // calls char* version with UTF-8 encoded data...
注意最后一个案例。由于运算符不知道它传递的是 ANSI 还是 UTF-8 数据,并且 CComBSTR
在传递 char*
数据时假定 ANSI,因此您应该使用不同的文字后缀来区分,以便您可以转换 UTF -8 正确,例如:
CComBSTR operator "" _utf8bstr (const char* str, std::size_t len)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conv;
std::wstring wstr = conv.from_bytes(std::string(str, len));
return CComBSTR(wstr.length(), wstr.c_str());
}
iFoo->function( u8"HELLO"_utf8bstr );
当调用需要 BSTR 的函数时,最好能够编写如下内容:
iFoo->function( bs"HELLO" );
然而,我知道的唯一解决方法是使用调用 SysAllocString
等的包装器,例如:
iFoo->function( WideString(L"HELLO").c_bstr() );
有点丑。实际上是否有创建 BSTR
文字的选项?
动机:更易于阅读的代码,以及通过避免分配和释放来提高运行时性能。
澄清:我只是在谈论调用者(即我们)拥有 BSTR 所有权的情况,例如:调用一个接受 BSTR [in]
的函数范围。当然,向将继续尝试释放字符串的函数提供指向 BSTR 文字的指针是愚蠢的。
用户定义的文字将是可行的方法:
"HELLO"_bstr
调用 template<char...> BSTR operator "" _bstr ( const char*, std::size_t)
然后可以调用 SysAllocString()
VS14 中的新功能。
[编辑]
根据评论,return 一个 _bstr_t
或其他 class 可能更好,它拥有 SysAllocString()
结果的所有权并隐式转换为 BSTR
。这个临时文件将在完整表达式的末尾被销毁,因此 after iFoo->function( "HELLO"_bstr );
returns.
为了跟进@MSalters 的回答,自定义的用户定义文字可能如下所示:
CComBSTR operator "" _bstr (const char* str, std::size_t len)
{
return CComBSTR(len, str);
}
然后你可以这样做(因为 CComBSTR
定义了 BSTR
转换运算符):
iFoo->function( "HELLO"_bstr );
您甚至可以为多个输入字符串文字类型重载运算符:
CComBSTR operator "" _bstr (const wchar_t* str, std::size_t len)
{
return CComBSTR(len, str);
}
CComBSTR operator "" _bstr (const char16_t* str, std::size_t len)
{
return CComBSTR(len, (wchar_t*)str);
}
iFoo->function( L"HELLO"_bstr ); // calls wchar_t* version with UTF-16 encoded data
iFoo->function( u"HELLO"_bstr ); // calls char16_t* version with UTF-16 encoded data
iFoo->function( u8"HELLO"_bstr ); // calls char* version with UTF-8 encoded data...
注意最后一个案例。由于运算符不知道它传递的是 ANSI 还是 UTF-8 数据,并且 CComBSTR
在传递 char*
数据时假定 ANSI,因此您应该使用不同的文字后缀来区分,以便您可以转换 UTF -8 正确,例如:
CComBSTR operator "" _utf8bstr (const char* str, std::size_t len)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conv;
std::wstring wstr = conv.from_bytes(std::string(str, len));
return CComBSTR(wstr.length(), wstr.c_str());
}
iFoo->function( u8"HELLO"_utf8bstr );