简体   繁体   中英

Difference between std::decay and std::remove_reference

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM