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

Почему шаблоны типа С++ 11 не являются шаблонами?

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

Я понимаю, что шаблоны псевдонимов не могут быть специализированными и, следовательно, can not в настоящее время используются для реализации типов типов непосредственно 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++ неохотно открывают пространства имен, будут явно определены (если они вообще будут изменены).

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

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


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

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

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

4b9b3361

Ответ 1

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

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

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

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

Обновление

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

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

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

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

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

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

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

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

И в С++ 1z:

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

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

Ответ 2

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

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

Ответ 3

В качестве полной боковой заметки, поскольку, похоже, существует путаница в том, как псевдонимы могут или не могут помочь в виде, например 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), поэтому это нам не помогает. Извините!