Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

auto&

68 views
Skip to first unread message

Vir Campestris

unread,
Jun 12, 2017, 4:28:51 PM6/12/17
to
Why is it that when I call a function that returns a reference, and
assign the result to an auto, it copies the value rather than declaring
the auto as a reference?

e.g.

std::vector<char> v;
...
auto c = v[0];
auto& r = v[0]

c is a char; to get a reference I must explicitly say so.

Andy

Gareth Owen

unread,
Jun 12, 2017, 4:47:28 PM6/12/17
to
As a rationale, I'd say
i) principle of least surprise
ii) because if a function returns a reference, then auto couldn't
be used to declare a non-reference variable, which would make it a
hell of a lot less useful. There's no syntax for "concrete type for
referred to by reference on RHS"

std::vector<int> a;
// ... initialize ...
auto val = a[3];
// most of the time I probably don't want val to be a reference here
val += ... ; // don't want a[3] to change.

Alf P. Steinbach

unread,
Jun 12, 2017, 5:46:55 PM6/12/17
to
On 12-Jun-17 10:28 PM, Vir Campestris wrote:
> Why is it that when I call a function that returns a reference, and
> assign the result to an auto, it copies the value rather than declaring
> the auto as a reference?

I think Gareth Owen, in his reply, gave a good/likely possibility for
the rationale, namely the principle of least surprise.

But re the technical, you can view `auto` as `decltype` + `std::decay`.

Here are `std::decay<T>` rules quoted from cppreference.com:

• If T names the type "array of U" or "reference to array of U", the
member typedef type is U*.

• Otherwise, if T is a function type F or a reference thereto, the
member typedef type is std::add_pointer<F>::type.

• Otherwise, the member typedef type is
std::remove_cv<std::remove_reference<T>::type>::type.

So, array-ness, function-ness, const-ness, volatile-ness and
reference-ness are removed.


> e.g.
>
> std::vector<char> v;
> ...
> auto c = v[0];
> auto& r = v[0]
>
> c is a char; to get a reference I must explicitly say so.

My main `auto` annoyance is that instead of

const ptr_<auto> p = foo();

… I must write something like

const auto p = pointer_result( foo() );

… to explicitly indicate the expected pointer-ness of the foo() result,
or else I'd have to use the operator notation; i.e., that `auto` is by
far not as powerful as template function argument deduction. :(


Cheers!,

- Alf

Chris Vine

unread,
Jun 12, 2017, 7:20:17 PM6/12/17
to
Thems is the rules. auto mimics template type deduction, and discards
references and const (and volatile) qualifiers. If you want the
reference or cv qualifier to be detected, use decltype(auto), which
uses decltype type deduction rules.

(For completeness, you were initializing not assigning. Initializing a
value type copies.)

Chris

--------------------------

Öö Tiib

unread,
Jun 14, 2017, 4:27:58 AM6/14/17
to
On Tuesday, 13 June 2017 00:46:55 UTC+3, Alf P. Steinbach wrote:
> My main `auto` annoyance is that instead of
>
> const ptr_<auto> p = foo();
>
> … I must write something like
>
> const auto p = pointer_result( foo() );
>
> … to explicitly indicate the expected pointer-ness of the foo() result,
> or else I'd have to use the operator notation; i.e., that `auto` is by
> far not as powerful as template function argument deduction. :(

I likely misunderstand the essence of that annoyance. May be that
because raw pointers are rare in code or may be because the
motivating code above reminds me about 'std::auto_ptr' (that was
quite bad trap). ;)

So ... did you want to embed following static_assert (invisibly or
less visibly)?

auto const p = foo();
static_assert(std::is_pointer<decltype(p)>::value
, "p must be raw pointer");

For me it feels fine to make noise about something being required
to be a raw pointer like that (if it is important).

Alf P. Steinbach

unread,
Jun 14, 2017, 4:34:32 AM6/14/17
to
The `static_assert` is good for the compiler.

But it's IMO not so good for the human: one has to read it and analyze
it, rather than just see it.

Well that could be alleviated via a macro, but. :)


Cheers!,

- Alf

Öö Tiib

unread,
Jun 14, 2017, 11:51:57 AM6/14/17
to
The point of static_assert is to fail fast and when failing then get clear
explanation with zero run-time cost. Most of asserts and static_asserts
and other debug checks I usually skip when reading code unless I have
issue related to those checks being too harsh or feeble.
Blocks of such checks are often sizable part of code base i mature project
but provide no functionality just check sanity of code.

> Well that could be alleviated via a macro, but. :)

Hmm ... macros have been, yes, good for producing debugging-related
code since majority of available reflection in C++ (like __FILE__, __LINE__
and __FUNCTION__) have been macros. Reflection is sometimes needed
for to be able to fail more clearly.


Vir Campestris

unread,
Jun 15, 2017, 4:40:06 PM6/15/17
to
On 12/06/2017 22:46, Alf P. Steinbach wrote:
> But re the technical, you can view `auto` as `decltype` + `std::decay`.

It was the technical stuff I was looking for.

It bit me because I assumed that because the function returned a
reference, auto would be a reference. I'll admit I was being lazy - I've
been writing C the last few years, and the coding standards where I used
to work said "Only use auto when there is no choice".

Thank you.
Andy
0 new messages