Разница между std:: decay и std:: удалить ссылку

когда метапрограммирование шаблонов на 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?

2 ответов


удаление ссылки оставит const и volatile. Если это то, чего вы хотите, то этого будет достаточно.

удаление cvref делает большую часть того, что делает decay, но не преобразует типы функций и типы массивов в указатели.

decay преобразует тип таким образом, что вы можете разумно хранить его копию в массиве или в struct, или вернуть его или передать его в функцию.


рассмотрим, например,

#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-qualifer,remove_reference не будет. Он просто очистит "справочную" часть типа.

С ссылка:

применяет lvalue-to-rvalue, array-to-pointer и function-to-pointer неявные преобразования в тип T, удаляет CV-квалификаторы и определяет результирующий тип как тип элемента typedef.

std::decay будет выполните больше преобразований типов, чем std::remove_reference.

есть также дополнительные модификаторы типов для более тонких приложений, которые будут выполнять только выбранные части набора возможных преобразований decay, например,remove_cv, remove_volatile или, в C++20, remove_cvref.