Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between add_lvalue_reference_t<T> and T&

Suppose you have a template argument T.

What are the differences 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 which?

like image 430
Uroc327 Avatar asked Aug 21 '15 18:08

Uroc327


2 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 is just T const, for example.

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

T& and T&& are ill-formed when T is cv void, but these templates are well-formed, just giving the original type back.

  • add_pointer_t<T> and T*?

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

Which should you use?

  • In general, the alias templates can be used to prevent deduction of T. Of course, that means that if you want deduction, you should avoid them.
  • The alias templates can be used as template template arguments to a template that takes a type transformation as a parameter.
  • The alias templates that differ in behaviour from alternatives like T* are useful in generic code since they "do the right thing". For example, if T is deduced from an argument of type T&&, then T* does the wrong thing when the argument is an lvalue, since it tries 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.
like image 86
Brian Bi Avatar answered Nov 17 '22 02:11

Brian Bi


According to what I see in 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 difference for example if T is non referenceable type void. add_lvalue_reference_t<void>::type = void and void& = compile-time error

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

add_pointer_t<T> and T* - difference when T is reference, because there is no such thing as pointer to reference. add_pointer_t<T> is equivalent to std::remove_reference<T>::type*

like image 21
Elohim Meth Avatar answered Nov 17 '22 00:11

Elohim Meth