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
при явном создании шаблона:
template class Foo<int>;
Я уверен, что есть другие случаи, которые я пропустил, но суть в том, что эти два ключевых слова не эквивалентны, и это некоторые распространенные случаи, когда вам нужно использовать одно или другое.
template <typename T> typename Foo {};
, потому что Foo <T> определенно является классом.std::vector<int>::value_type
это не зависимый тип, он вам там не нуженtypename
- он нужен вам только в том случае, если тип зависит от параметра шаблона, скажем,template<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
это не зависимый тип. Зависимые типы - это имена, которые зависят от параметра шаблона , напримерfoo<param_t>::some_type
, не сами параметры шаблона.typename
, то естьtemplate <typename> typename C
.GCC 5
, G ++ позволяет теперь TypeName в качестве параметра шаблона шаблона .Для именования параметров шаблона
typename
иclass
эквивалентны. §14.1.2:typename
однако это возможно в другом контексте при использовании шаблонов - намекнуть компилятору, что вы ссылаетесь на зависимый тип. §14.6.2:Пример:
Без
typename
компилятора не могу вообще сказать, имеете ли вы в виду тип или нет.источник
Хотя технических различий нет, я видел, как эти два понятия обозначают несколько разные вещи.
Для шаблона, который должен принимать любой тип как T, включая встроенные модули (такие как массив)
Для шаблона, который будет работать только там, где T - реальный класс.
Но имейте в виду, что это просто стиль, который используют некоторые люди. Не предписано стандартом или не применяется компиляторами
источник
T t; int i = t.toInt();
), то вам нужен «реальный класс», и ваш код не будет компилироваться, если вы предоставитеint
для негоT
...class
подразумевает, что вы не просто ожидаете "значение", возможно, поддерживающее некоторые операторы, копируете или перемещаете конструкцию и / или присваивание, но конкретно нуждаетесь в типе, поддерживающем некоторую семантику доступа к члену. Самый быстрый взгляд на объявление затем устанавливает ожидания и препятствует, например, предоставляя встроенные типы дляclass
параметров, когда это, безусловно, будет ошибкой.Container
сам по себе является шаблоном с двумя параметрами типа.источник
template<template<class U> class V> struct C {};
Этот фрагмент фрагмента взят из учебника по С ++. Хотя я уверен, что это неправильно.
Каждому параметру типа должен предшествовать ключевое слово class или typename:
Эти ключевые слова имеют одинаковое значение и могут использоваться взаимозаменяемо в списке параметров шаблона. Список параметров шаблона может использовать оба ключевых слова:
Может показаться более интуитивно понятным использовать ключевое слово typename, а не class для обозначения параметра типа шаблона. В конце концов, мы можем использовать встроенные (не классовые) типы в качестве аргумента типа шаблона. Более того, typename более четко указывает на то, что следующее имя является именем типа. Однако typename было добавлено в C ++ после того, как шаблоны уже широко используются; некоторые программисты продолжают использовать класс исключительно
источник