Search code examples
c++c++11constantstype-traitsdecltype

Why doesn't std::remove_const remove const qualifier?


Note that I use std::thread just to get readable types in the errors:

int main() {
    const int * first;
    using deref = decltype(*first);
    std::thread s = std::remove_const<deref>::type{}; // const int ???
    std::thread s2 = deref{}; // const int
    std::thread s3 = std::remove_const<const int>::type{}; // int 
}

It seems as if remove_const<deref>::type is const int, not mutable int as I would expect.


Solution

  • Note that *first is an lvalue expression, then the result type of decltype(*first) would be const int&, i.e. a reference to const int. The reference is not const itself (it can't be const-qualified, there's no such thing like int& const), using std::remove_const on it will yield the same type, i.e. const int&.

    See decltype specifier:

    1. If the argument is any other expression of type T, and

    b) if the value category of expression is lvalue, then decltype yields T&;

    You could use std::remove_const with std::remove_reference together:

    std::remove_const<std::remove_reference<deref>::type>::type // -> int
                                            ^^^^^               // -> const int &
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        // -> const int
    

    BTW:

    Note that I use std::thread just to get readable types in the errors:

    Note that it doesn't give the correct type for this case. Here's a class template helper for this from the Effective Modern C++ (Scott Meyers):

    template<typename T>
    class TD;
    

    and use it as

    TD<deref> td;
    

    You'll get the error message containing the type of deref, e.g. from clang:

    prog.cc:16:11: error: implicit instantiation of undefined template 'TD<const int &>'
    TD<deref> td;
              ^