Используйте 'class' или 'typename' для параметров шаблона?
Возможный дубликат:
C++ разница ключевых слов "typename" и "class" в шаблонах
При определении шаблона функции или шаблона класса в C++ можно написать так:
template <class T> ...
или можно написать это:
template <typename T> ...
Есть ли веская причина, чтобы предпочесть одно другому?
Я принял самый популярный (и интересный) ответ, но реальным ответом, похоже, было "Нет, нет веской причины отдавать предпочтение одному".
- Они эквивалентны (кроме как указано ниже).
- У некоторых людей есть причины всегда использовать
typename
. - У некоторых людей есть причины всегда использовать
class
. - У некоторых людей есть причины использовать оба.
- Некоторым людям все равно, какой из них они используют.
Однако обратите внимание, что до C++ 17 в случае параметров шаблона шаблона требовалось использовать class
вместо typename
. Смотрите user1428839 ответ ниже. (Но этот конкретный случай не является вопросом предпочтения, это было требование языка.)
Ответы
Ответ 1
Стэн Липпман рассказал об этом здесь. Я думал, что это интересно.
Сводка: Первоначально Stroustrup использовал class
для указания типов в шаблонах, чтобы не вводить новое ключевое слово. Некоторые в комитете обеспокоены тем, что эта перегрузка ключевого слова привела к путанице. Позже, комитет ввел новое ключевое слово typename
для разрешения синтаксической неоднозначности, и решил позволить ей также использоваться для указания типов шаблонов, чтобы уменьшить путаницу, но для обеспечения обратной совместимости, class
сохранил свое перегруженное значение.
Ответ 2
В соответствии с Скоттом Майерсом, Эффективным С++ (3-е изд.), пунктом 42 (который, конечно же, должен быть окончательным ответом) - разница "ничего".
Совет должен использовать "класс", если ожидается, что T всегда будет классом с "typename", если ожидаются другие типы (int, char * whatever). Рассмотрите его как подсказку использования.
Ответ 3
В качестве дополнения ко всем вышеперечисленным публикациям использование ключевого слова class
является обязательным (вплоть до С++ 14) при работе с параметрами шаблона шаблона, например:
template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };
В этом примере typename Container
вызвала бы ошибку компилятора, что-то вроде этого:
error: expected 'class' before 'Container'
Ответ 4
Я предпочитаю использовать typename, потому что я не поклонник перегруженных ключевых слов (jeez - сколько разных значений имеет static
для разных контекстов?).
Ответ 5
Есть разница, и вы должны предпочесть class
на typename
.
Но почему?
typename
является незаконным для аргументов шаблона шаблона, поэтому, чтобы быть последовательным, вы должны использовать class
:
template<template<class> typename MyTemplate, class Bar> class Foo { }; // :(
template<template<class> class MyTemplate, class Bar> class Foo { }; // :)
Ответ 6
В ответ на Mike B я предпочитаю использовать "класс", поскольку в шаблоне "typename" имеет перегруженное значение, но "класс" не, Возьмите пример проверенного целочисленного типа:
template <class IntegerType>
class smart_integer {
public:
typedef integer_traits<Integer> traits;
IntegerType operator+=(IntegerType value){
typedef typename traits::larger_integer_t larger_t;
larger_t interm = larger_t(myValue) + larger_t(value);
if(interm > traits::max() || interm < traits::min())
throw overflow();
myValue = IntegerType(interm);
}
}
larger_integer_t
является зависимым именем, поэтому для этого требуется 'typename', чтобы синтаксический анализатор мог распознать, что larger_integer_t
является типом. class, с другой стороны, не имеет такого перегруженного значения.
Это... или я просто ленив от души. Я набираю "класс" гораздо чаще, чем "typename", и, таким образом, его легче набирать. Или это может быть признаком того, что я пишу слишком много кода OO.
Ответ 7
Просто чистая история. Цитата от Стэна Липпмана:
Причина для двух ключевых слов - историческая. В исходной спецификации шаблона Stroustrup повторно использовал существующее ключевое слово класса, чтобы указать параметр типа, а не вводить новое ключевое слово, которое, разумеется, может сломать существующие программы. Дело не в том, что новое ключевое слово не рассматривалось, а просто потому, что оно не считалось необходимым с учетом его потенциального нарушения. И до стандарта ISO-С++ это был единственный способ объявить параметр типа.
Но нужно использовать typename, а не class!
См. Ссылку для получения дополнительной информации, но подумайте о следующем коде:
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops ...
};
Ответ 8
Это вообще не имеет значения, но класс делает его похожим на то, что T может быть только классом, хотя он может, конечно, быть любым типом. Так что typename более точно. С другой стороны, большинство людей используют класс, поэтому, вероятно, легче читать в целом.
Ответ 9
Насколько я знаю, неважно, какой из них вы используете. Они эквивалентны в глазах компилятора. Используйте то, что вы предпочитаете. Обычно я использую класс.
Ответ 10
Расширение комментария DarenW.
После того, как имя и класс не будут отличаться друг от друга, может быть все еще справедливым строгое использование. Используйте класс только в том случае, если это действительно класс, и typename, когда его базовый тип, например char.
Эти типы действительно также принимаются вместо typename
шаблон < char myc = '/' >
который был бы в этом случае даже превосходил typename или class.
Подумайте о "хитрости" или разборчивости для других людей. И на самом деле подумайте, что стороннее программное обеспечение/скрипты могут попытаться использовать код/информацию, чтобы угадать, что происходит с шаблоном (подумайте о swig).