简体   繁体   中英

Is there a way to write a BSTR literal?

When calling a function that expects a BSTR it'd be nice to be able to write something like:

iFoo->function( bs"HELLO" );

However the only workaround I'm aware of is to use a wrapper that calls SysAllocString etc., eg:

iFoo->function( WideString(L"HELLO").c_bstr() );

which is kind of ugly. Is there actually such an option to create a BSTR literal?

Motivation: easier-to-read code, and faster runtime performance by avoiding an allocation and deallocation.

Clarification: I am only talking about situations where the caller (ie us) has ownership of the BSTR, for example: calling a function that takes a BSTR [in] parameter. Of course, it would be silly to supply a pointer to a BSTR literal to a function which will go on to try and free the string.

User defined literals would be the way to go:

"HELLO"_bstr calls template<char...> BSTR operator "" _bstr ( const char*, std::size_t) which can then call SysAllocString()

New in VS14.

[edit]

Based on the comments, it might be better to return a _bstr_t or other class which takes ownership of the SysAllocString() result and implicitly converts to BSTR . This temporary will be destroyed at the end of the full expression, and therefore after iFoo->function( "HELLO"_bstr ); returns.

To follow up on @MSalters's answer, a custom user-defined literal could look something like this:

CComBSTR operator "" _bstr (const char* str, std::size_t len)
{
    return CComBSTR(len, str);
}

Then you can do this (as CComBSTR has a BSTR conversion operator defined):

iFoo->function( "HELLO"_bstr );

You can even overload the operator for multiple input string literal types:

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...

Note the last case. Since the operator will not know whether it is being passed ANSI or UTF-8 data, and CComBSTR assumes ANSI when passed char* data, you should use a different literal suffix to differentiate so you can convert the UTF-8 correctly, eg:

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 );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM