c++c++11type-traits

Why isn't a const reference considered const using the is_const type trait?


I was rather surprised that the following code:

#include <iostream>
#include <type_traits>

using namespace std;

int main(int argc, char* argv[]) {
    cout << boolalpha << is_const<const float&>::value << endl;

    return 0;
 }

Prints false. Removing the reference works correctly:

#include <iostream>
#include <type_traits>

using namespace std;

int main(int argc, char* argv[]) {
    cout << boolalpha << is_const<remove_reference<const float&>::type>::value << endl;

    return 0;
 }

Printing out true.

Both were compiled with g++ -std=c++11 test.cpp, using G++ version:

g++ (Ubuntu 5.3.0-1ubuntu1~14.04) 5.3.0 20151204

Thinking about it, I can understand that there are two types in play here: the reference type and the type that is referenced. The type that is referenced is const, so the second case makes sense. For the first case, I would expect it to either return if the referenced type is const or always true instead, because references AFAIK can't be "reassigned".

Why does it return false instead?


Solution

  • The outcome is correct.

    References are never const, because they cannot be cv-qualified. You are correct in saying that they cannot be reassigned (and are, as such, immutable in a sense), but that is not the same as being const-qualified.

    If you got true purely because the referent is const, then that would be completely inconsistent with the meaning of is_const in all other cases. Consider, for example, pointers. What should is_const<int const*>::value be?