When template metaprogramming in C++, I often run into something like the following:
template <typename T>
S<T> make_wrapper(T&& t) { return S<T>(std::forward<T>(t)); }
I know I should use something like std::decay
in the return type, but why wouldn't std::remove_reference
work as well? What's the difference here? What about std::remove_cvref
?
Consider for example
#include <type_traits>
int main()
{
static_assert(std::is_same_v<
std::decay_t<const int&>,
std::remove_reference_t<const int&>
>); // int != const int
}
std::decay
will remove any cv-qualifer, remove_reference
won't. It will just strip the "reference" part of the type.
From the reference :
Applies lvalue-to-rvalue, array-to-pointer, and function-to-pointer implicit conversions to the type T, removes cv-qualifiers, and defines the resulting type as the member typedef type.
Therefore std::decay
will perform way more type conversions than std::remove_reference
.
There are also further type modifiers for more nuanced applications that will only perform selected parts of the set of possible transformations decay
does, like remove_cv
, remove_volatile
or, in C++20, remove_cvref
.
Removing reference would leave const
and volatile
. If that is what you want, then it will suffice.
Removing cvref does most of what decay does, but doesn't convert function types and array types to pointers.
decay converts a type in a way that you could reasonably store a copy of it in an array or in a struct
, or return it from or pass it to a function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.