Почему С++ поддерживает два ключевых слова – class и typename как параметры типов
Недавно меня спросили, почему у нас поддерживаются и class, и typename в С++ для обозначения параметров типов, ведь они не несут никакой значимости для платформы – например, class может подразумевать нативный тип, а typename – тип CLI. Оба они используются для параметризации в шаблонах и заменяются на заданный пользователем тип.
Почему два ключевых слова? Потому что так исторически сложилось. В первоначальной спецификации шаблонов Страуструп повторно использовал имеющееся ключевое слово class для задания параметра типа, вместо того чтобы вводить новое ключевое слово, что могло бы испортить имеющиеся программы. Не то чтобы не хотелось ввести новое ключевое слово – просто не хотелось потенциально привнести ошибки. И вплоть до стандарта ISO-C++ это был единственный способ объявить параметр типа.
Повторное использование имеющегося ключевого слова всегда сеет неразбериху. Мы увидели, что начинающие программисты ограничиваются использованием классов в качестве параметров типов, но не встроенных типов или указателей. Так что, похоже, то что мы не ввели новое ключевое слово, было ошибкой.
Во время стандартизации мы обнаружили, что некоторые конструкции трактуются как выражения, в то время как предполагалось, что это объявления. Например:
C++ Source Code:
1
template <class T>
2
class Demonstration
3
{
4
public:
5
void method()
6
{
7
T::A *aObj; // oops...
8
//...
9
};
В то время как программист предполагает, что конструкция, содержащая aObj, является объявлением указателя на вложенный тип А в типовом параметре Т, грамматика языка интерпретирует это как арифметическое выражение: умножение статического члена А типа Т на aObj и отбрасывание результата. Ну что за хрень! (Такое затруднительное положение невозможно для общих типов – нет способа убедиться, что любой Т содержит А, так что рантайм может безопасно построить экземпляр общего типа.)
Комиссия решила, что новое ключевое слово – это как раз то, что нужно, чтобы обойти навязчивую идею компилятора по поводу выражений. Это слово говорит само за себя – typename. Когда оно входит в конструкцию такого типа:
C++ Source Code:
typename T::A* a6; // declare pointer to T’s A
оно сообщает компилятору трактовать последующую информацию как объявление. Ну раз уж ввели новое ключевое слово, черт возьми, так почему бы не исправить путаницу, вызванную использованием class в шаблонах? Конечно же, учитывая большое количество написанного кода, книг, статей, разговоров и постов с использованием слова class, они решили оставить и его поддержку. Вот почему их два.
Довольно забавно, а я до прочтения этой статьи не знал и тоже думал, что class - для классов, а typename - для базовых типов, а то что можно юзать базовые типы там где class - это автобоксинг. Оказалось, все намного проще.
Я до прочтения сей статьи вообще не знал ключевого слова typename. Как говорилось где-то, C++ невозможно изучить полностью - все время узнаешь что-то новое.