Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::remove_const with const references

Tags:

Why does std::remove_const not convert const T& to T&? This admittedly rather contrived example demonstrates my question:

#include <type_traits>  int main() {     int a = 42;     std::remove_const<const int&>::type b(a);      // This assertion fails     static_assert(         !std::is_same<decltype(b), const int&>::value,         "Why did remove_const not remove const?"     );      return 0; } 

The above case is trivially easy to fix, so for context, imagine the following:

#include <iostream>  template <typename T> struct Selector {     constexpr static const char* value = "default"; };  template <typename T> struct Selector<T&> {     constexpr static const char* value = "reference"; };  template <typename T> struct Selector<const T&> {     constexpr static const char* value = "constref"; };  int main() {     std::cout         << Selector<typename std::remove_const<const int&>::type>::value         << std::endl;      return 0; } 

In the above example, I'd expect reference to be shown, rather than constref.

like image 729
dafrito Avatar asked Apr 08 '13 19:04

dafrito


People also ask

How to remove const from reference c++?

In order to strip const away, you first have to apply std::remove_reference , then apply std::remove_const , and then (if desired) apply std::add_lvalue_reference (or whatever is appropriate in your case).

Does const reference make a copy?

Typically it will create a copy of the protos, 'typically' because compiler might add some optimizations depending on the specific code paths, but while coding we need not worry about that.

Are references const?

The grammar doesn't allow you to declare a “const reference” because a reference is inherently const . Once you bind a reference to refer to an object, you cannot bind it to refer to a different object.


1 Answers

std::remove_const removes top level const-qualifications. In const T&, which is equivalent to T const&, the qualification is not top-level: in fact, it does not apply to the reference itself (that would be meaningless, because references are immutable by definition), but to the referenced type.

Table 52 in Paragraph 20.9.7.1 of the C++11 Standard specifies, regarding std::remove_const:

The member typedef type shall name the same type as T except that any top-level const-qualifier has been removed. [ Example: remove_const<const volatile int>::type evaluates to volatile int, whereas remove_const<const int*>::type evaluates to const int*. — end example ]

In order to strip const away, you first have to apply std::remove_reference, then apply std::remove_const, and then (if desired) apply std::add_lvalue_reference (or whatever is appropriate in your case).

NOTE: As Xeo mentions in the comment, you may consider using an alias template such as Unqualified to perform the first two steps, i.e. strip away the reference, then strip away the const- (and volatile-) qualification.

like image 116
Andy Prowl Avatar answered Sep 21 '22 12:09

Andy Prowl