Date: Sun, 28 Mar 2021 23:18:51 -0400
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
>> 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#SEC106
> 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:
> 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).
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.
>
>> 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#SEC106
> 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:
> 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).
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 <http://www.fornux.com>
Received on 2021-03-28 22:18:58