Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non const When Capture Reference by Value?

Tags:

c++

g++

c++17

I am looking at 8.4.4.1 in n4713 C++ standard:

void f() {
float x, &r = x;
[=] {
   decltype(x) y1; // y1 has type float
   decltype((x)) y2 = y1; // y2 has type float const& because this lambda is not mutable and x is an lvalue
   decltype(r) r1 = y1; // r1 has type float&
   decltype((r)) r2 = y2; // r2 has type float const&
};
}

The standard says r2 has type float const&, and then I tried to print out the types:

#include <iostream>

template <class T>
void print_type() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main () {
    float x, &r = x;
    [=] {
        print_type<decltype(x)>();
        print_type<decltype((x))>();
        print_type<decltype(r)>();
        print_type<decltype((r))>();
    }();
}

It gave:

void print_type() [with T = float]
void print_type() [with T = const float&]
void print_type() [with T = float&]
void print_type() [with T = float&]

The type of r2 is float& instead of float const&. Did I do something wrong?

I used g++ 8.3.1 to compile. I also tried 9.1.0 but same thing.

like image 639
HCSF Avatar asked Jul 07 '20 14:07

HCSF


People also ask

What is non const reference?

I think this means that making a reference a "const" when it is referenced to a non const object does absolutely nothing. We may as well take that const keyword out when defining that reference. Not true. You may not modify the a non- const object through a const reference.

Can a const reference refer to a non const object?

No. A reference is simply an alias for an existing object.

Does const reference make a copy?

Not just a copy; it is also a const copy. So you cannot modify it, invoke any non-const members from it, or pass it as a non-const parameter to any function. If you want a modifiable copy, lose the const decl on protos .


1 Answers

As the question already mentions, the type of decltype((r)) must be float const& according to the standard since we are in not-mutable lambda.

GCC incorrectly prints type of decltype((r)) in your example. Clang and Visual Studio process your example correctly.

And even GCC has the issue only with type printing, it does not allow the user to change the value referenced by r or to initialize float & reference from r:

int main () {
    float x = 0, &r = x;
    [=]() {
        [[maybe_unused]] decltype((r)) q = r;
    }();
}

https://gcc.godbolt.org/z/9oKzoeaq9

like image 94
Fedor Avatar answered Oct 18 '22 21:10

Fedor