Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is the const lost in an expression like `const T&` where T is an rvalue reference?

I’m working on a templated class, and given an incoming type T the template needs to map to a "safe" const reference. (This is essentially to avoid handing the ability to mutate to a wrapped function when it’s called; see here for the real code).

The original author wrote something equivalent to this:

template <typename T>
using SafeReference =
    std::conditional_t<std::is_scalar_v<T>, T, const T&>;

The scalar part isn’t interesting here, but what’s interesting is const T&. This looks right to me, but it’s not:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct Foo{};
using Bar = Foo&&;

// A failing static assert, and a reduced version. It turns out `const Bar&`
// is `Foo&`.
static_assert(std::is_same_v<const Foo&, SafeReference<Bar>>);
static_assert(std::is_same_v<const Foo&, const Bar&>);

I understand that Foo&& becomes Foo& due to the rules for reference collapsing. I also understand that the const is probably "lost" because it tries to make a reference const rather than making the referred-to type const. But I don’t even know what to Google in order to confirm that.

Which part of the standard says that the const is "lost" in an expression like const T& for a templated T expanding to an rvalue reference?

>Solution :

Which part of the standard says that the const is "lost" in an expression like const T& for a templated T expanding to an rvalue reference?

From dcl.ref/p6:

If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv TR creates the type lvalue reference to T, while an attempt to create the type rvalue reference to cv TR creates the type TR.

The quote probably explains the behavior you’re seeing.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading