9

在 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

4

2 回答 2

13

考虑例如

#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.

于 2017-12-18T15:42:33.680 回答
11

删除参考将离开constand volatile。如果这就是你想要的,那么它就足够了。

删除 cvref 完成了衰减的大部分工作,但不会将函数类型和数组类型转换为指针。

衰减以一种您可以合理地将其副本存储在数组或 a 中的方式转换类型struct,或者将其从函数中返回或传递给函数。

于 2017-12-18T16:22:45.487 回答