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>andconst volatile Tadd_const_t<T>andconst Tadd_volatile_t<T>andvolatile Tadd_lvalue_reference_t<T>andT&add_rvalue_reference_t<T>andT&&add_pointer_t<T>andT*?
Why should I use add_rvalue_reference_t<T> instead of T&& , for example. Are there any rules when to choose what?
add_cv_t<T>andconst volatile Tadd_const_t<T>andconst Tadd_volatile_t<T>andvolatile T
No difference; the definition of add_const<T>::type true, for example, T const .
add_lvalue_reference_t<T>andT&add_rvalue_reference_t<T>andT&&
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>andT*?
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
TOf 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, ifTis inferred from an argument of typeT&&, thenT*does the wrong thing when the argument is an lvalue, since it is trying to declare a pointer to an lvalue reference. Butstd::add_pointer_t<T>will give a pointer to the actual type of the argument.
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*
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.