typename
i class
są wymienne w podstawowym przypadku określania szablonu:
template<class T>
class Foo
{
};
i
template<typename T>
class Foo
{
};
są równoważne.
To powiedziawszy, istnieją szczególne przypadki, w których istnieje różnica między typename
iclass
.
Pierwszy dotyczy typów zależnych. typename
służy do deklarowania, gdy odwołujesz się do typu zagnieżdżonego, który zależy od innego parametru szablonu, takiego jak typedef
w tym przykładzie:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
Drugi, który faktycznie pokazujesz w swoim pytaniu, choć możesz nie zdawać sobie z tego sprawy:
template < template < typename, typename > class Container, typename Type >
Określając szablon szablon The class
kluczowe muszą być używane jak wyżej - to nie zamiennie ze typename
w tym przypadku (uwaga: od C ++ 17 oba słowa kluczowe są dozwolone w tym przypadku) .
Musisz także użyć class
podczas jawnego tworzenia szablonu:
template class Foo<int>;
Jestem pewien, że są inne przypadki, które przegapiłem, ale sedno jest następujące: te dwa słowa kluczowe nie są równoważne i są to niektóre typowe przypadki, w których musisz użyć jednego lub drugiego.
template <typename T> typename Foo {};
, ponieważ Foo <T> jest zdecydowanie klasą.std::vector<int>::value_type
nie jest typem zależnym, nie potrzebujesz gotypename
tam - potrzebujesz go tylko, jeśli typ zależy od parametru szablonu, powiedzmytemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
nie jest typem zależnym. Typy zależne to nazwy zależne od parametru szablonu , npfoo<param_t>::some_type
. Same parametry szablonu.typename
, tjtemplate <typename> typename C
.GCC 5
, G ++ pozwala teraz TypeName w parametrze szablon szablon .Do nazewnictwa parametrów szablonu
typename
iclass
są one równoważne. §14.1.2:typename
jest to jednak możliwe w innym kontekście podczas korzystania z szablonów - aby wskazać kompilatorowi, że masz na myśli typ zależny. 14.6.2:Przykład:
Bez
typename
kompilatora nie można ogólnie stwierdzić, czy masz na myśli typ, czy nie.źródło
Chociaż nie ma żadnej różnicy technicznej, widziałem, że oba oznaczały nieco inne rzeczy.
Dla szablonu, który powinien akceptować dowolny typ jako T, w tym wbudowane (takie jak tablica)
Dla szablonu, który będzie działał tylko tam, gdzie T jest prawdziwą klasą.
Pamiętaj jednak, że niektórzy ludzie używają tego stylu. Nie jest to wymagane przez standard lub wymuszone przez kompilatory
źródło
T t; int i = t.toInt();
), potrzebujesz „prawdziwej klasy”, a twój kod nie będzie się kompilował, jeśli dostarczyszint
dlaT
...class
oznacza, że nie tylko oczekujesz „wartości”, być może wspierającej niektórych operatorów, kopiującej lub przenoszącej konstrukcję i / lub przypisanie, ale konkretnie potrzebujesz typu obsługującego niektóre semantyki dostępu do elementu. Najszybsze spojrzenie na deklarację określa następnie oczekiwania i odradza np. Dostarczanie wbudowanych typówclass
parametrów, gdy z pewnością byłby to błąd.Container
sam w sobie jest szablonem z dwoma parametrami typu.źródło
template<template<class U> class V> struct C {};
Ten fragment kodu pochodzi z książki z podstawami języka C ++. Chociaż jestem pewien, że to źle.
Każdy parametr typu musi być poprzedzony klasą słowa kluczowego lub nazwą typu:
Te słowa kluczowe mają to samo znaczenie i mogą być używane zamiennie w liście parametrów szablonu. Lista parametrów szablonu może zawierać oba słowa kluczowe:
Bardziej intuicyjne może być użycie słowa kluczowego nazwa_typu zamiast klasy do określenia parametru typu szablonu. W końcu możemy używać wbudowanych (nieklasowych) typów jako argumentów typu szablonu. Ponadto nazwa typu wyraźniej wskazuje, że następująca nazwa jest nazwą typu. Jednak nazwa typu została dodana do C ++ po tym, jak szablony były już w powszechnym użyciu; niektórzy programiści nadal używają wyłącznie klasy
źródło