Skip to content

Add _bst user-defined literal for BSTR-shaped wide strings#647

Open
jonwis wants to merge 1 commit into
microsoft:masterfrom
jonwis:jonwis/static-bstrs-2
Open

Add _bst user-defined literal for BSTR-shaped wide strings#647
jonwis wants to merge 1 commit into
microsoft:masterfrom
jonwis:jonwis/static-bstrs-2

Conversation

@jonwis

@jonwis jonwis commented Jun 27, 2026

Copy link
Copy Markdown
Member

Reduce global initializers and intermediate allocations with a BSTR-compatible string literal.

// Unnecessary globals - 
const wil::unique_bstr g_bst(SysAllocString(L"kittens"));
const auto g_bst2 { wil::make_bstr_failfast(L"puppies"); };

HRESULT UseBstr(BSTR bst);
void call_bstr_function() {
    UseBstr(g_bst.get());

    // Unnecessary local allocation
    auto propName = wil::make_bstr_failfast(L"waffleCount");
    UseBstr(propName.get());

    // !!super mega ultra danger!! - not passing a real bstr...
    UseBstr(L"kablooie");
}

Instead, literals:

const auto g_bst = L"kittens"_bst;
const auto g_bst2 = L"puppies"_bst;

void call_bstr_function() {
    UseBstr(g_bst);
    UseBstr(L"waffleCount"_bst);
}

(Thanks Copilot!)

C++20 only. Captures the literal as a class-type NTTP so storage is
sized exactly to the literal length; constexpr-constructible, no heap,
no lifetime hazards.

    void Use(BSTR);
    Use(L\"foo\"_bst);

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread include/wil/stl.h

WI_NODISCARD constexpr operator BSTR() const WI_NOEXCEPT
{
return const_cast<wchar_t*>(&m_data[0]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to guard against N=0? In that case this is getting the address of a zero-size buffer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zero sized arrays are not valid in C++

Comment thread include/wil/stl.h
template <wchar_literal_storage Lit>
WI_NODISCARD constexpr auto operator""_bst() WI_NOEXCEPT
{
return bstr_literal_t<sizeof(Lit.value) / sizeof(wchar_t)>{Lit.value};

@dunhor dunhor Jul 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add something like:

static constexpr const std::size_t size = N;

or a (constexpr) size() method to wchar_literal_storage so you don't need the manual length calculation

Comment thread tests/StlTests.cpp
#if __WI_LIBCPP_STD_VER >= 20
SECTION("Literal creates a valid BSTR")
{
const auto literal = L"foo"_bst;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also include a constexpr validation

Comment thread include/wil/stl.h
struct bstr_literal_t
{
unsigned long m_byte_length;
wchar_t m_data[N];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider: something like static_assert(offsetof(m_data) == 4)

Comment thread include/wil/stl.h
};

template <wchar_literal_storage Lit>
WI_NODISCARD constexpr auto operator""_bst() WI_NOEXCEPT

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My personal expectation is that this would be _bstr, but I don't use BSTRs enough to know how common of an "abbreviation" this is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing worth mentioning is that "bst" could stand for "binary search tree" (not that that would make much sense for a user defined literal)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants