Sorry I guess 20 years ago is not in everybody's curriculum.
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 function. 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: https://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_5.html#SEC106As 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.
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
So the aforementioned example is simple but it really points out a new concept: "stack-safe return variables" if you want.Oh, and the meaningfully useful part of this "named return value" thing is already under discussion: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2021/p2025r2.html 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).
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;
}
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.