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

для шаблонов я видел оба заявления:

template < typename T >
template < class T >

в чем разница?

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

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

5 ответов


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 в этом случае (Примечание: так как C++17 оба ключевых слова разрешены в этом случае).

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

template class Foo<int>;

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


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

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

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

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

пример:

typename some_template<T>::some_type

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


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

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

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

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

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

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


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

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

каждому параметру типа должно предшествовать ключевое слово class или 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, а не class для обозначения параметра типа шаблона. В конце концов, мы можем использовать встроенные (неклассовые) типы в качестве аргумента типа шаблона. Кроме того, typename более четко указывает, что следующее имя является именем типа. Однако typename был добавлен в C++ после того, как шаблоны уже широко использовались; некоторые программисты продолжают использовать класс исключительно