Разница ключевых слов "typename" и "class" в шаблонах?

Для шаблонов я видел обе декларации:

template < typename T >
template < class T >

Какая разница?

И что именно означают эти ключевые слова в следующем примере (взято из немецкой статьи Википедии о шаблонах)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};

Ответы

Ответ 1

typename и class взаимозаменяемы в основном случае указания шаблона:

template<class T>
class Foo
{
};

и

template<typename T>
class Foo
{
};

эквивалентны.

Сказав это, существуют конкретные случаи, когда существует разница между typename и class.

Первый - в случае зависимых типов. typename используется для объявления, когда вы ссылаетесь на вложенный тип, который зависит от другого параметра шаблона, такого как typedef в этом примере:

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

Второй, который вы на самом деле показываете в своем вопросе, хотя вы этого не понимаете:

template < template < typename, typename > class Container, typename Type >

При указании шаблона шаблона ключевое слово class ДОЛЖНО использоваться, как указано выше, в этом случае оно не заменяется на typename (примечание: поскольку С++ 17 в этом случае разрешены оба ключевых слова).

Вы также должны использовать class при явном создании экземпляра шаблона:

template class Foo<int>;

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

Ответ 2

Для присвоения имен шаблонам параметры typename и class эквивалентны. §14.1.2:

Нет семантической разницы между классом и typename в Шаблон-параметры.

typename однако возможен в другом контексте при использовании шаблонов - намекнуть на компилятор, что вы ссылаетесь на зависимый тип. §14.6.2:

Имя, используемое в объявлении шаблона или определение, и это зависит от шаблон-параметр предполагается не назовите тип, если соответствующее имя lookup находит имя типа или имя имеет ключевое слово typename.

Пример:

typename some_template<T>::some_type

Без typename компилятор вообще не может сказать, ссылаетесь ли вы на тип или нет.

Ответ 3

Пока нет технической разницы, я видел, что два используются для обозначения немного разных вещей.

Для шаблона, который должен принимать любой тип как T, включая встроенные (например, массив)

template<typename T>
class Foo { ... }

Для шаблона, который будет работать только там, где T - настоящий класс.

template<class T>
class Foo { ... }

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

Ответ 4

  • Никакой разницы
  • Параметр типа шаблона Container сам является шаблоном с двумя параметрами типа.

Ответ 5

Этот фрагмент фрагмента из С++ учебника. Хотя я уверен, что это неправильно.

Каждому параметру типа должен предшествовать класс keyword или typename:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

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

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

Может показаться более понятным использовать ключевое слово typename, а не класс, чтобы назначить параметр типа шаблона. В конце концов, мы можем использовать встроенные (неклассические) типы в качестве аргумента типа шаблона. Более того, typename более четко указывает, что имя, которое следует за именем типа. Тем не менее, typename был добавлен в С++ после того, как шаблоны уже широко использовались; некоторые программисты продолжают использовать класс исключительно