Обнаружение констант вложенного типа - PullRequest
8 голосов
/ 13 января 2011

Обычно, если мне нужно определить, является ли тип const, я просто использую boost::is_const.Тем не менее, я столкнулся с проблемой при попытке обнаружить константу вложенного типа.Рассмотрим следующий шаблон характеристик, который специализирован для константных типов:

template <class T>
struct traits
{
    typedef T& reference;
};

template <class T>
struct traits<const T>
{
    typedef T const& reference;
};

Проблема в том, что boost::is_const, похоже, не обнаруживает, что traits<const T>::reference является const типом.

Например:

std::cout << std::boolalpha;
std::cout << boost::is_const<traits<int>::reference>::value << " ";
std::cout << boost::is_const<traits<const int>::reference>::value << std::endl;

Это выводит: false false

Почему не выводится false true?

Ответы [ 3 ]

13 голосов
/ 13 января 2011

Поскольку ссылка не является константой, это тип, на который она ссылается, является константой.Правильно, нет постоянных ссылок.Итак, представьте, что ссылка является указателем, тогда разницу легче понять: int const* не const, int *const является const.

Используйте remove_reference для получения фактического типа const:

cout << boost::is_const<
            boost::remove_reference<int const&>::type>::value << '\n';
6 голосов
/ 13 января 2011

Потому что ссылки не const. :)

У вас есть ref-to-const (рассмотрим грубый аналог, int const*, где у указателя int есть контекст const, а у самого указателя нет). Стандарт смешивает терминологию здесь, но я избегаю термина «const ref», который вводит в заблуждение.

Ссылки по своей природе являются неизменными, поскольку их можно только инициализировать, а затем повторно не связывать, но это не делает их const.

Вы можете удалить ссылку из типа с помощью boost::remove_reference (как указано в других ответах).

4 голосов
/ 13 января 2011

Хорошо, вы заметили, что is_const<int const&>::value также ложно?Это.Нечто подобное должно быть в числе первых, что вы пытаетесь отлаживать, как шаблоны.Еще одна вещь, которую вы можете использовать, это принтер типов:

template < typename T > struct print;

Когда вы создаете экземпляр, вы получите то, что есть в выводе ошибки, с большинством реализаций.

Попробуйте решить эту текущую проблему:

is_const< remove_reference< traits<int const>::reference >::type >::value

...