C++ Logo

std-proposals

Advanced search

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

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Thu, 24 Jul 2025 18:00:11 +0000
IMO the use case is completely bizarre.
And with this you could also make technically valid code such as this:
A(B(c));
to be flagged as invalid even though there's no way to tell if it is.
Why?

[[no_discard]] was introduced for interfaces that returned something, that could be easily be ignored, but because of what they do or how they work if you do discard it, you would almost certainly be doing something wrong.
It poses no requirement that it need to be specifically assigned as long as you use it in some capacity, it is at least implied that you acknowledge that a return object exists and that you must do something about it.
It doesn't tell you how to write your code, only that code must be written to deal with it.

This is not that.
All this does is force you to assign a name to it.
If you completely ignore its existence after it has been assigned, this feature is completely fine with it.
Which begs the question as to why it forced you to write code in a specific way, instead of adding anything useful?

It's bizarre. What does it even achieve other than force you to write code in a very specific way?


________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Jarrad Waterloo via Std-Proposals <std-proposals_at_[hidden]>
Sent: Thursday, July 24, 2025 5:39:58 PM
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Cc: Jarrad Waterloo <descender76_at_[hidden]>
Subject: Re: [std-proposals] Similar to [[no_discard]], but store in a variable, maybe call it [[must_store]]

It's also good documentation on how the function call should be used safely even if there is no static analyzer to enforce it.

On Thu, Jul 24, 2025 at 11:18 AM Jeremy Rifkin via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
Why is an attribute needed for this? Why not rely on static analysis tools?

Jeremy

On Tue, Jul 22, 2025 at 06:05 Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
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.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]<mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals_at_lists.isocpp.org<mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-07-24 18:00:20