在 C++ 中进行模板元编程时,我经常遇到如下情况:
template <typename T>
S<T> make_wrapper(T&& t) { return S<T>(std::forward<T>(t)); }
我知道我应该std::decay在返回类型中使用类似的东西,但为什么不能std::remove_reference正常工作?这里有什么区别?怎么样std::remove_cvref?
考虑例如
#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将删除任何 cv 限定符,remove_reference不会。它只会剥离类型的“参考”部分。
从参考:
对类型 T 应用左值到右值、数组到指针和函数到指针的隐式转换,删除 cv 限定符,并将结果类型定义为成员 typedef 类型。
因此std::decay将执行比std::remove_reference.
还有更多类型修饰符用于更细微的应用程序,这些应用程序将仅执行一组可能的转换的选定部分decay,例如remove_cv,remove_volatile或 C++20 中的remove_cvref.
删除参考将离开constand volatile。如果这就是你想要的,那么它就足够了。
删除 cvref 完成了衰减的大部分工作,但不会将函数类型和数组类型转换为指针。
衰减以一种您可以合理地将其副本存储在数组或 a 中的方式转换类型struct,或者将其从函数中返回或传递给函数。