Разница между 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,

Другие вопросы по тегам