C++ Logo

std-proposals

Advanced search

[std-proposals] Similar to [[no_discard]], but store in a variable, maybe call it [[must_store]]

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 22 Jul 2025 13:05:27 +0100
Sometimes we want the return value from a function not only to not be
discarded, but more specifically we want it to be stored inside a
local variable.

Consider a method like std::synchronized_value::rlock, which returns
by value a type similar to "std::lock_guard". We always want this
return value to be stored in a variable:

    auto mylock = mysyncvalue.wlock();

If the programmer is only going to call one method on it, then they
should instead use "operator->", therefore we can consider the
following to be incorrect:

    mysyncvalue.wlock()->DoSomething();

and instead it should be replaced with:

     mysyncvalue->DoSomething();

Therefore, it would make sense to mark the 'wlock' method as [[must_store]].

Another example is the wxWidgets library, with the class wxString. The
method, "wxString::c_str" looks like this:

    wxCStrData wxString::c_str() const
    {
        return wxCStrData(this);
    }

When you invoke "c_str" on a wxString object, it returns a wxCStrData
object. The wxCStrData class has two implicit conversions:

    operator const wchar_t*() const { return AsWChar(); }
    operator const char*() const { return AsChar(); }

If you build the wxWidgets library in Unicode mode, then the method
"AsWChar" returns a pointer to a pre-existing array. However if you
build the wxWidgets library in ASCII mode, and then invoke "AsWChar",
it dynamically allocates a temporary array and gives you the pointer.
This could allow us to put a very interesting bug into our code:

    wxString mystr( wxS("Hello I'm a monkey") );

    wchar_t *const p = mystr.c_str();

    wcout << p << endl;

The above code will work fine on Unicode, but might crash on ASCII.
The dynamically-allocated array gets destroyed when "c_str()" returns.
The solution is to do this:

    wxString mystr("Hello I'm a monkey");

    auto const converter = mystr.c_str();
    wchar_t *const p = converter;

    wcout << p << endl;

If we can mark a function as [[must_store]] then it will prevent stuff
like this from making its way into the release build.

Received on 2025-07-22 12:05:41