Подтвердить что ты не робот

Std:: remove_const с ссылками на const

Почему std::remove_const не конвертировать const T& в T&? Этот, по общему признанию, довольно надуманный пример демонстрирует мой вопрос:

#include <type_traits>

int main()
{
    int a = 42;
    std::remove_const<const int&>::type b(a);

    // This assertion fails
    static_assert(
        !std::is_same<decltype(b), const int&>::value,
        "Why did remove_const not remove const?"
    );

    return 0;
}

Вышеприведенный случай тривиально легко исправить, поэтому для контекста представьте себе следующее:

#include <iostream>

template <typename T>
struct Selector
{
    constexpr static const char* value = "default";
};

template <typename T>
struct Selector<T&>
{
    constexpr static const char* value = "reference";
};

template <typename T>
struct Selector<const T&>
{
    constexpr static const char* value = "constref";
};

int main()
{
    std::cout
        << Selector<typename std::remove_const<const int&>::type>::value
        << std::endl;

    return 0;
}

В приведенном выше примере я ожидал бы reference, а не constref.

4b9b3361

Ответ 1

std::remove_const удаляет верхние уровни const -qualifications. В const T&, эквивалентном T const&, квалификация не является верхним уровнем: на самом деле она не применяется к самой ссылке (это было бы бессмысленно, потому что ссылки являются неизменяемыми по определению), но к ссылочным тип.

Таблица 52 в Параграфе 20.9.7.1 Стандарта С++ 11 указывает на std::remove_const:

Тип typedef-члена должен иметь тот же тип, что и T, за исключением того, что любой верхний уровень const-qualifier был удален. [Пример: remove_const<const volatile int>::type оценивает volatile int, тогда как remove_const<const int*>::type оценивает до const int*. - конец примера]

Чтобы вырезать const, вам сначала нужно применить std::remove_reference, затем применить std::remove_const, а затем (при желании) применить std::add_lvalue_reference (или что-то подходящее в вашем случае).

ПРИМЕЧАНИЕ.. Как Xeo упоминается в комментарии, вы можете рассмотреть с использованием шаблона псевдонимов, такого как Unqualified, чтобы выполнить первые два шага, то есть отбросить ссылку, а затем отделить квалификацию const - (и volatile-).