Какова была проблема, решаемая новым синтаксисом "use" для шаблонов typedefs?
В С++ 11 вы можете создать "псевдоним типа", выполнив что-то вроде
template <typename T>
using stringpair = std::pair<std::string, T>;
Но это отклонение от того, что вы ожидаете от шаблона typedef:
template <typename T>
typedef std::pair<std::string, T> stringpair;
Итак, возникает вопрос: зачем им придумывать новый синтаксис? что это не работало со старым синтаксисом typedef
?
Я понимаю, что последний бит не компилируется, но почему его нельзя компилировать?
Ответы
Ответ 1
Из предложения WG21 N1489 Шаблонные псевдонимы (от Stroustrup и Dos Reis):
Было предложено (повторно) использовать ключевое слово typedef
, как это сделано в [4], чтобы ввести шаблонные псевдонимы:
template<class T>
typedef std::vector<T, MyAllocator<T> > Vec;
Эта нотация имеет то преимущество, что используется ключевое слово, уже известное ввести псевдоним типа. Однако он также демонстрирует несколько недостатков среди которых путаница использования ключевого слова, известного псевдоним для имени типа в контексте, где псевдоним не обозначает тип, но шаблон; Vec не является псевдонимом для типа, и не должен берется за имя typedef. Название Vec - это имя для семьи std::vector<o, MyAllocator<o> >
, где пуля является заполнителем для имени типа. Следовательно, мы не предлагаем синтаксис typedef.
С другой стороны, предложение
template<class T>
using Vec = std::vector<T, MyAllocator<T> >;
можно прочитать/интерпретировать как: отныне я буду использовать Vec<T>
как синоним std::vector<T, MyAllocator<T> >
. С этим чтением новый синтаксис для псевдонимов кажется достаточно логичным.
Документ [4], упомянутый в приведенной выше цитате, был предварительным предложением WG21 N1406 Предлагаемое дополнение к С++: шаблоны Typedef (Херб Саттер). Он использует и другой синтаксис (typedef
vs using
), а также другую номенклатуру (typedef templates vs template aliases). Предлагаемый синтаксис Herb не сделал этого, но номенклатуру иногда можно найти в неофициальных дискуссиях.
Ответ 2
Я просто коснусь самого себя:
http://www.stroustrup.com/C++11FAQ.html#template-alias
Использование ключевого слова используется для получения линейного обозначения "имя, за которым следует к чему это относится". Мы попытались с обычным и запутанным typedef, но так и не удалось получить полный и последовательный до тех пор, пока мы не остановимся на менее неясном синтаксисе.
Ответ 3
(tl; dr: using
поддерживает шаблоны, а typedef
- нет.)
Как кажется, вы уже знаете, разница между двумя примерами без шаблонов - это ничего:
[C++11: 7.1.3/2]:
Имя typedef также может быть введено с помощью объявления alias. Идентификатор, следующий за ключевым словом using
, становится typedef-name и необязательным атрибутом-спецификатором-seq, следующим за идентификатором, к этому typedef-name. Он имеет ту же семантику, что и его спецификатор typedef
. В частности, он не определяет новый тип и не должен отображаться в идентификаторе типа.
Однако шаблон typedef
не существует!
[C++11: 14.5.7/1]:
Объявление шаблона, в котором объявление является объявлением alias (раздел 7), объявляет идентификатор шаблоном псевдонимов. Шаблон псевдонимов - это имя для семейства типов. Имя шаблона псевдонима - это имя-шаблон.
Почему они просто не использовали синтаксис typedef
? Ну, я думаю, что typedef
- это просто "старый" стиль и, учитывая использование using
в других контекстах, было решено, что новая функциональность должна принимать форму using
для согласованности.
Ответ 4
Еще одна причина для нового синтаксиса - typedefs для функций, массивов и подобных конструкций становится немного понятнее.
Ссылка на массив до/после:
typedef int(&my_type)[3];
using my_type = int(&)[3];
Массив указателей функций до/после:
typedef void(*my_type[3])();
using my_type = void(*[3])();