Разница ключевых слов "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 был добавлен в С++ после того, как шаблоны уже широко использовались; некоторые программисты продолжают использовать класс исключительно