Почему шаблоны типа С++ 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>
.
Ответы
Ответ 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
), поэтому это нам не помогает. Извините!