Использовать 'class' или 'typename' для параметров шаблона?

Возможный дубликат:
Различия в ключевых словах "typename" и "class" в шаблонах C++

При определении шаблона функции или шаблона класса в C++ можно написать так:

template <class T> ...

или можно написать это:

template <typename T> ...

Есть ли веская причина предпочитать одно другому?


Я принял самый популярный (и интересный) ответ, но реальный ответ, кажется, "Нет, нет веской причины предпочитать один другому".

  • Они эквивалентны (за исключением отмеченного ниже).
  • У некоторых людей есть причины всегда использовать typename,
  • У некоторых людей есть причины всегда использовать class,
  • У некоторых людей есть причины использовать оба.
  • Некоторым людям все равно, какой из них они используют.

Обратите внимание, однако, что в случае параметров шаблона шаблона, использование class вместо typename необходимо. См. User1428839 ответ ниже. (Но этот конкретный случай не является вопросом предпочтения, это требование языка.) (Также это изменится с c++17)

10 ответов

Решение

Стэн Липпман говорил об этом здесь. Я думал, что это было интересно.

Резюме: Stroustrup первоначально используется class указывать типы в шаблонах, чтобы не вводить новое ключевое слово. Некоторые члены комитета обеспокоены тем, что перегрузка ключевого слова привела к путанице. Позже комитет ввел новое ключевое слово typename разрешить синтаксическую неоднозначность и решил разрешить использовать его также для указания типов шаблонов, чтобы уменьшить путаницу, но для обратной совместимости, class сохранил свой перегруженный смысл.

Согласно Скотту Майерсу, "Эффективный C++" (3-е изд.), Пункт 42 (который, конечно, должен быть окончательным ответом), - "ничто".

Совет должен использовать "класс", если ожидается, что T всегда будет классом, с "typename", если ожидаются другие типы (int, char* и т. Д.). Считайте это подсказкой использования.

В дополнение ко всем вышеперечисленным сообщениям, использование class Ключевое слово принудительно (до C++14 включительно) при работе с параметрами шаблона шаблона, например:

template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };

В этом примере typename Container сгенерировал бы ошибку компилятора, что-то вроде этого:

error: expected 'class' before 'Container'

Я предпочитаю использовать typename, потому что я не фанат перегруженных ключевых слов (блин - сколько разных значений static есть для разных контекстов?).

Есть разница, и вы должны предпочесть class в typename,

Но почему?

typename недопустимо для аргументов шаблона шаблона, поэтому, чтобы быть последовательным, вы должны использовать class:

template<template<class> typename MyTemplate, class Bar> class Foo { };    //  :(
template<template<class>    class MyTemplate, class Bar> class Foo { };    //  :)

В ответ на Mike B я предпочитаю использовать "class", так как в шаблоне "typename" имеет перегруженное значение, а "class" - нет. Возьмите этот проверенный пример целочисленного типа:

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', и, следовательно, набираю его гораздо проще. Или это может быть признаком того, что я пишу слишком много ОО-кода.

Просто чистая история. Цитата Стэна Липпмана:

Причина для двух ключевых слов историческая. В исходной спецификации шаблона Stroustrup повторно использовал существующее ключевое слово class, чтобы указать параметр типа, а не вводить новое ключевое слово, которое, конечно, могло бы сломать существующие программы. Дело не в том, что новое ключевое слово не рассматривалось - просто оно не считалось необходимым, учитывая его потенциальное нарушение. И до стандарта ISO-C++ это был единственный способ объявить параметр типа.

Но лучше использовать имя типа, а не класс! Смотрите ссылку для получения дополнительной информации, но подумайте о следующем коде:

template <class T>
class Demonstration { 
public:
void method() {
   T::A *aObj; // oops ...
};

Это не имеет значения, но класс делает его похожим на то, что T может быть только классом, в то время как, конечно, он может быть любого типа. Таким образом, typename является более точным. С другой стороны, большинство людей используют класс, так что, вероятно, его легче читать в целом.

Насколько я знаю, не имеет значения, какой вы используете. Они эквивалентны в глазах компилятора. Используйте тот, который вы предпочитаете. Я обычно использую класс.

Расширяя комментарий DarenW.

Если не принято считать, что typename и class сильно отличаются друг от друга, все еще может быть строгим соблюдение правил их использования. Используйте class только в том случае, если это действительно класс, а typename, когда это базовый тип, такой как char.

Эти типы действительно также принимаются вместо typename

шаблон< char myc = '/'>

который в этом случае даже превосходит typename или class.

Подумайте о "осторожности" или понятности для других людей. И на самом деле учтите, что сторонние программы / скрипты могут пытаться использовать код / ​​информацию, чтобы угадать, что происходит с шаблоном (рассмотрим swig).

Другие вопросы по тегам