Consider the following C++ program:
#include <iostream>
template<typename T>
class A
{
public:
explicit A(T& x) : x_(x){}
const T& get() { return x_; }
private:
T x_;
};
int main()
{
int x = 42;
A<int&>(x).get() = 43; // compiles fine, even though get() looks like it returns a const ref
std::cout << x << '\n';
}
The program compiles OK and outputs 43. This suggests that the seemingly const reference returned by get() is in fact a non-const reference, because it allows to modifies the value it refers to.
Is it a rule of reference collapsing that causes this behaviour?
How to enforce that the reference returned from get() behaves like a const reference, that is, it doesn't allow to modify the value it refers to?
Is it a rule of reference collapsing that causes this behaviour?
Yes. You have:
T = int&
const T& = const (int&) &
References can't be const
(you can't rebind them anyways, so it's ignored) and a reference to a reference is just a reference.
So you have
const T& = int&
To fix this, you need to apply const
to the underlying type, which you can do like this by removing the reference:
const std::remove_reference_t<T>& get() { return x_; }
// ^^^^^^^^^^^^^^^^^^^^^^^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With