The difference between add_lvalue_reference_t <T> and T &

Suppose you have a template argument T

What's the difference between

  • add_cv_t<T> and const volatile T
  • add_const_t<T> and const T
  • add_volatile_t<T> and volatile T
  • add_lvalue_reference_t<T> and T&
  • add_rvalue_reference_t<T> and T&&
  • add_pointer_t<T> and T* ?

Why should I use add_rvalue_reference_t<T> instead of T&& , for example. Are there any rules when to choose what?

+7
c ++ generic-programming c ++ 11 templates
source share
3 answers
  • add_cv_t<T> and const volatile T
  • add_const_t<T> and const T
  • add_volatile_t<T> and volatile T

No difference; the definition of add_const<T>::type true, for example, T const .

  • add_lvalue_reference_t<T> and T&
  • add_rvalue_reference_t<T> and T&&

T& and T&& poorly formed when T is cv void , but these patterns are well formed by simply returning the original type.

  • add_pointer_t<T> and T* ?

add_pointer_t<T> equivalent to std::remove_reference<T>::type* . That is, if T is a reference type, it gives a pointer to the reference type. On the other hand, T* will be poorly formed, since you cannot have a pointer to a link.

What should you use?

  • In general, alias patterns can be used to prevent the subtraction of T Of course, this means that if you want to subtract, you must avoid them.
  • Alias ​​patterns can be used as arguments to a pattern template for a pattern that takes type conversion as a parameter.
  • Alias ​​patterns that differ in behavior from alternatives like T* are useful in general code because they "do the right thing." For example, if T is inferred from an argument of type T&& , then T* does the wrong thing when the argument is an lvalue, since it is trying to declare a pointer to an lvalue reference. But std::add_pointer_t<T> will give a pointer to the actual type of the argument.
+10
source share

According to what I see in the STL source:

add_cv_t<T> and const volatile T - no difference

add_const_t<T> and const T - no difference

add_volatile_t<T> and volatile T - no difference

add_lvalue_reference_t<T> and T& - there is a difference, for example, if T is not a void reference type. add_lvalue_reference_t<void>::type = void and void& = compile-time error

add_rvalue_reference_t<T> and T&& are the same as above

add_pointer_t<T> and T* are the difference when T is a link because there is no pointer to the link. add_pointer_t<T> equivalent to std::remove_reference<T>::type*

+3
source share

In most cases, std::add_rvalue_reference_t<T> equivalent to T&& . However, link folding rules and the-rules-that-dictate-which-types-are-referenceable may have the wrong code for your code if you ignore it.

However, there are cases where the type of the static member type will be different, since T is not a reference type. For example, std::add_rvalue_reference_t<void> allows void and (using another template that you mentioned as an example) std::add_pointer_t<T&> allowed T* (if you want to cause chaos, the required ritual is std::add_pointer_t<std::add_rvalue_reference_t<void>> :))

Respecting the use, it can be used as a template template parameter to do some kind of damn black magic. In any case, things like std::is_rvalue_reference_t<T> or std::remove_reference_t<T> are usually more often used when manipulating type reference attributes.

0
source share

All Articles