Why is `const T&` not sure to be const?

  • A+
template<typename T> void f(T a, const T& b) {     ++a; // ok     ++b; // also ok! }  template<typename T> void g(T n) {     f<T>(n, n); }  int main() {     int n{};     g<int&>(n); } 

Please note: b is of const T& and ++b is ok!

Why is const T& not sure to be const?


Welcome to const and reference collapsing. When you have const T& the reference gets applied to T and so does the const. You call g like


so you have specified that T is a int&. When we apply a reference to an lvalue reference int& & it collapses to just int&. Then we get to the rule from [dcl.ref]/1 which states that is you apply const to a reference it is discarded so int& const just becomes int& (note that yo can't actually declare int& const, it has to come from a typedef or template). That means for


you are actually calling

void f(int& a, int& b) 

and you are not actually modifying a constant.

Had you called g as

g<int>(n); // or just g(n); 

Then T would be int and f would have been stamped out as

void f(int a, const int& b) 

since T isn't a reference anymore the const and the & get applied to it and you would have received a compiler error for trying to modify a constant variable.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: