Почему черты типа C ++ 11 не являются шаблонами псевдонимов? - PullRequest
23 голосов
/ 29 февраля 2012

Аналогичный вопрос: Почему type_traits реализован с помощью специализированных шаблонных структур вместо constexpr? - но с другим ответом.

Я понимаю, что шаблоны псевдонимов не могут быть специализированными и, следовательно, в настоящее время не могут использоваться для непосредственной реализации признаков типа 1 .Однако это сознательное решение комитета, и, насколько я вижу, нет технических причин запрещать это.

Так что не имело бы смысла реализовывать черты типа в качестве шаблонов псевдонимов, упрощаяих синтаксис?

Рассмотрим

 typename enable_if<is_pointer<T>::value, size_t>::type
 address(T p);

против

 enable_if<is_pointer<T>, size_t> address(T p);

Конечно, это приводит к критическому изменению интерфейса при переходе от Boost.TypeTraits - но действительно ли это такая большая проблема?

В конце концов, в любом случае необходимо будет изменить код, так как типы находятся в разных пространствах имен и, как многие современные программисты C ++ не хотят открывать пространства имен, будут квалифицированыявно (если это вообще будет изменено).

С другой стороны, это значительно упрощает код.А учитывая, что метапрограммирование шаблонов часто становится глубоко вложенным, запутанным и сложным, кажется очевидным, что более понятный интерфейс полезен.

Я что-то упустил?Если нет, то я был бы признателен за ответ, который не является просто догадкой, а основан на (и может привести) знании обоснования решения комитета.


1 Но очень хорошо косвенно!Рассмотрим:

template <typename T> using is_pointer = typename meta::is_pointer<T>::type;

Где meta::is_pointer<T> соответствует текущему типу std::is_pointer<T>.

Ответы [ 3 ]

16 голосов
/ 29 февраля 2012

Наиболее конкретный ответ на ваш вопрос: никто никогда не предлагал сделать это таким образом.

Комитет по стандартам C ++ - это многонациональная, многопрофильная группа добровольцев.Вы думаете об этом как проектный комитет в рамках одной организации.Комитет по стандартам C ++ буквально не может ничего сделать без предложения о включении слов в проект стандарта.

Я полагаю, что причина, по которой не было никакого предложения, заключается в том, что черты типа были ранним предложением, а реализация надстройки началась в далеком прошлом.примерно до 2000 года. И псевдонимы шаблонов были запоздалыми в реализации.Многие из членов комитета неохотно предлагают то, что они не осуществили.И у вас просто не было возможности реализовать ваше предложение.

Было много давления для выпуска C ++ 11.Он действительно был предназначен для отправки в 2009 году, и когда эта дата откатилась, было очень сложно что-либо сделать с рабочим документом, кроме исправления уже рассмотренных функций.В какой-то момент вы должны отложить на задний план замечательные новые идеи, чтобы вы никогда не отправили.

Обновление

Начиная с C ++ 14,TransformationTraits (те, которые приводят к типу) теперь имеют написание псевдонима шаблона, например:

template <bool b, class T = void>
  using enable_if_t = typename enable_if<b,T>::type;

И рабочий проект C ++ 1z теперь имеет написание переменных шаблона для признаков, приводящих к значениям:

template <class T>
  constexpr bool is_pointer_v = is_pointer<T>::value;

Кроме того, даже в C ++ 11 можно сделать:

typename enable_if<is_pointer<T>{}, size_t>::type
address(T p);

Т.е. вы можете использовать {} вместо ::value (при условии, что ваш компилятор поддерживает constexpr),В C ++ 14 это становится:

enable_if_t<is_pointer<T>{}, size_t>
address(T p);

И в C ++ 1z:

enable_if_t<is_pointer_v<T>, size_t>
address(T p);

Обратите внимание, что разница между C ++ 1z и C ++ 14 настолько минимальначто он даже не сохраняет символы, просто меняет {} на _v и меняет расположение этих двух символов.

2 голосов
/ 29 февраля 2012

Черты типа, как и некоторые другие библиотеки, включая <memory> и <functional>, были унаследованы от C ++ TR1.Хотя это был менее формальный документ, он был более формальным, чем Boost, и совместимость того стоила.

Кроме того, обратите внимание, что все признаки типа получены из std::integral_constant<bool>, в котором реализована функция преобразования constexpr вbool.Так что, по крайней мере, сохраняются ::value части, если вы того пожелаете.

1 голос
/ 01 марта 2012

В качестве полного примечания, поскольку кажется, что существует путаница в том, как псевдонимы могут или не могут помочь такой черте, как std::is_pointer:

Вы можете пойти по маршруту Boost.MPL и решить, что будете использовать интегральные константы в стиле Boost.MPL, что означает типы

template<typename Cond, typename Then = void>
using enable_if = typename std::enable_if<Cond::value, Then>::type;

// usage:
template<
    typename T
    , typename = enable_if<std::is_pointer<T>>
>
size_t address(T p);

или вы можете использовать вместо этого значения

template<bool Cond, typename Then>
using enable_if = typename std::enable_if<Cond, Then>::type;

// can use ::value
template<
    typename T
    , typename = enable_if<std::is_pointer<T>::value>>
>
size_t address(T p);

// or constexpr conversion operator
template<
    typename T
    , typename = enable_if<std::is_pointer<T> {}>
>
size_t address(T p);

Обратите внимание, что в последнем случае невозможно использовать enable_if<std::is_pointer<T>()>: std::is_pointer<T>() является типом функции (принимает void и возвращает std::is_pointer<T>) и является недопустимым, поскольку наш псевдоним принимает значение, а не тип в этот случай. Скобки гарантируют, что это константное выражение.

Как вы уже могли заметить, std::is_pointer вообще не использует псевдонимы шаблонов. Это неудивительно, так как в этой интересной части есть доступ к ::value, а не ::type: псевдонимы шаблонов могут помочь только с типами элементов. type член std::is_pointer не интересен, так как это интегральная константа в стиле Boost.MPL (в данном случае std::true_type или std::false_type), так что это нам не поможет. Извините!

...