On 3/28/21 10:44 PM, Jason McKesson via Std-Proposals wrote:

As such, it is unclear what exactly you want to change about the
language. It's also unclear why you would want to write code this way
instead of just returning the string and letting the *user* call the

What I have shown is one case of the need for the revival of the named return values, but using a workaround. For a proposal, the syntax could use what GCC was using:

As a general rule, if you're going to suggest something, you should
probably explain what it is, rather than just naming a term and
expecting people to Google it to find out what you actually want.
Sorry I guess 20 years ago is not in everybody's curriculum.
In any case, it's not clear how what you described is equivalent to
what you want. In the GCC feature, the "named return value" is of a
type exactly equivalent to the return type. And thus, the object whose
lifetime will be extended based on the caller will be the return
value's type. But in your examples, the return value is a `char
const*`, not the string object that owns it. So it's not clear how
what you've asked for would solve the problem in your examples
*without* returning a prvalue string (and therefore requiring the user
to use `c_str`).

Good point, I should have realized that. So I guess the old GCC's named return value is not powerful enough. Maybe the following syntax using square brackets could be used instead, this way the variable created before the call couldn't possibly be overridden by the user:

#include <string>

namespace personal


struct string : std::wstring


    typedef std::wstring base;


    char const * encoded_c_str() [std::string && r = std::string()]
        r = std::string(base::begin(), base::end());

        return r.c_str();


personal::string s = "Hello world";

cout << s.encoded_c_str() << endl; // will be just fine

Oh, and the meaningfully useful part of this "named return value"
thing is already under discussion:

Now, that wouldn't solve your problem either, because the problem both
"named return value" and "named guaranteed elision" solves is about
returning prvalues of objects that you don't want to invoke a
copy/move on. The problem you seem to be wanting to solve is to allow
a function to create two objects: the return value the user is
expected to use, and a "return value" that owns the first object so
that you can return dangling references that don't dangle.

Also given the class should abstract all functionality, the user shouldn't need to call the c_str() explicitly.
Why should it "abstract all functionality"? Also, your examples aren't
abstracting functionality; they're creating *different* functionality.
Your "c_str" equivalent returns a freshly allocated string and is
therefore not at all like the actual `c_str` function (and therefore
should have a different name).
So the aforementioned example is simple but it really points out a new concept: "stack-safe return variables" if you want.
If you're going to have a function that allocates a copy of the
string, the user ought to have the choice about what to do with that
allocation. They should be able to choose to store it as a managed
string, get a `char*` out of it, or whatever they want to do. Your way
forces them into one pattern of use, and if they want to store the
string long-term, they must copy it *again*.

Again this is a simple example but how about:

    char const * encoded_c_str() [std::ostringstream && r = std::ostringstream()]
        r << std::string(base::begin(), base::end());


        r << var1 << ", " << var2 << ", " << [...] ends;

        return r.str.c_str();


The alternative to these "stack-safe return variables" would be to have the temporary variable as a member of the encompassing class but it would require more memory space for each instance of the class.


Phil Bouchard
Founder & CTO
C.: (819) 328-4743

Fornux Logo