Разница между std::decay и std::remove_reference
При шаблонном метапрограммировании в 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, но не преобразует типы функций и типы массивов в указатели.
Распад преобразует тип таким образом, чтобы вы могли разумно сохранить его копию в массиве или в 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
,