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

Почему в шаблонах С++ используется синтаксис угловой скобки?

Титульный вопрос относится к проектным решениям на стандарте С++, который вводил шаблоны в 1990 году.

Почему дизайнеры использовали <> (угловые скобки) вместо, скажем, () (круглые скобки)? Это позволило бы сэкономить много программистов из ошибки смещения бит.

std::vector<std::vector<int>> // does not work until C++11

который был исправлен только на С++ 11. Я не вижу смысла вводить дополнительный синтаксис, например, когда, возможно, круглые скобки служили бы той же цели, сохраняя минимальные изменения. Установлено, что вы могли использовать

template(typename T) // Define template if round brackets could be used
mytemplate { ... }
...
...
mytemplate(mytemplate(int)) obj; //Instantiate template when round brackets could be used

Может ли кто-нибудь хорошо разбираться в истории С++ выкапывать оригинальное обоснование дизайна для использования угловых скобок? В качестве альтернативы вы можете показать, почему другие решения также не сработали бы?

4b9b3361

Ответ 1

Шаблоны были введены в документе USENIX 1988 года Parameterized Types for С++ от Bjarne Stroustrup, позже включенном в Справочное руководство Annotated С++, опубликованное в 1990 году ( версия до стандартизованного С++). Согласно документу,

Скобки <…> используются в предпочтении скобкам (…) отчасти до , подчеркивают различную природу аргументов шаблона (они будут оцениваться во время компиляции) и отчасти потому, что круглые скобки уже безнадежно запутаны в С++.

...

9,2. <…> vs (…)

Но зачем использовать скобки вместо круглых скобок? Как упоминалось ранее, в скобках уже много применений в С++. Синтаксический ключ (скобки <…>) может быть использован для напоминания пользователю о различной природе параметров типа (они оцениваются во время компиляции). Более того, использование круглых скобок может привести к довольно неясному коду:

template(int sz = 20) class buffer {
    buffer(int i = 10);
    // ...
};
buffer b1(100)(200);
buffer b2(100);      // b2(100)(10) or b2(20)(100)?
buffer b3;           // legal?

Эти проблемы станут серьезной практической проблемой, если будут приняты обозначения для явного устранения неоднозначных перегруженных вызовов функций. Выбранная альтернатива кажется намного более чистой:

template<int sz = 20> class buffer {
    buffer(sz)(int i = 10);
    // ...
};
buffer b1<100>(200);
buffer b2<100>;      // b2<100>(10)
buffer b3;           // b3<20>(10)
buffer b4(100);      // b4<20>(100)

В документе также объясняется, почему используются ключевые слова template и class.

Обратите внимание, что Stroustrup поместил <…> после имени переменной таким же образом, как int x[10], чтобы возразить против (…), хотя это место размещения никогда не используется нигде в документе.

Его аргумент о том, что "использование (…) может привести к неясному/неоднозначному коду", по-прежнему остается в силе. Как упоминалось в этом вопросительном комментарии, использование скобки T(x) приводит к неоднозначности с типом функции или вызовом функции (обратите внимание, что T может быть шаблоном функции, а допустимыми значениями С++ являются аргументы шаблона).

Аналогично, использование квадратных скобок T[x] приводит к двусмысленности с типом массива или индексированием.

Я не понимаю, почему T{x} еще не может быть использован, возможно, это просто не рассматривается, или, может быть, слишком уродливо использовать везде {…}.