Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 442
NoSenseEtAl Avatar asked Apr 17 '17 15:04

NoSenseEtAl


1 Answers

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;
          ^
like image 99
songyuanyao Avatar answered Nov 09 '22 09:11

songyuanyao