답변:
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>;
필자가 놓친 다른 사례가 있다고 확신하지만 결론은 다음과 같습니다.이 두 키워드는 동일하지 않으며 하나를 사용해야하는 일반적인 경우입니다.
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
와 class
동일합니다. §14.1.2 :
template-parameter에서 class와 typename 사이에는 의미 상 차이가 없습니다.
typename
그러나 템플릿을 사용할 때 다른 컨텍스트에서 컴파일러가 종속 유형을 참조하고 있음을 암시 할 수 있습니다. §14.6.2 :
템플리트 선언 또는 정의에 사용되며 템플리트 매개 변수에 종속 된 이름은 적용 가능한 이름 검색에서 유형 이름을 찾거나 이름이 키워드 typename에 의해 규정되지 않는 한 유형의 이름을 지정하지 않는 것으로 간주됩니다.
예:
typename some_template<T>::some_type
typename
컴파일러가 없으면 일반적으로 유형을 참조하는지 여부를 알 수 없습니다.
기술적 인 차이는 없지만 두 가지가 약간 다른 것을 나타내는 데 사용되었습니다.
내장 (예 : 배열)을 포함하여 모든 유형을 T로 수락 해야하는 템플릿
template<typename T>
class Foo { ... }
T가 실제 클래스 인 경우에만 작동하는 템플릿
template<class T>
class Foo { ... }
그러나 이것은 일부 사람들이 사용하는 스타일입니다. 표준에 의해 요구되거나 컴파일러에 의해 강제되지 않음
T t; int i = t.toInt();
다음) 당신은 "진짜 클래스"를해야하고, 사용자가 제공하는 경우 코드는 컴파일되지 않습니다 int
에 대한 T
...
class
당신은 아마도 일부 연산자를 지원하는 "가치"를 기대할뿐 아니라, 생성 및 / 또는 할당을 복사 또는 이동시킬뿐 아니라, 특히 멤버 액세스 의미를 지원하는 타입이 필요하다는 것을 암시한다. 선언문을 가장 빨리 살펴보면 예상치 못한 class
오류 일 때 매개 변수 에 내장 유형을 제공하는 등의 기대와 낙담을 설정합니다 .
Container
자체는 두 가지 유형 매개 변수 가있는 템플릿입니다.
template<template<class U> class V> struct C {};
이 스 니펫 조각은 C ++ 입문서입니다. 나는 이것이 틀렸다고 확신하지만.
각 유형 매개 변수 앞에 키워드 클래스 또는 유형 이름이 와야합니다.
// 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이 C ++에 추가되었습니다. 일부 프로그래머는 계속 클래스를 독점적으로 사용합니다
template <typename T> typename Foo {};
Foo <T>는 클래스이므로 클래스 의 처음 두 비트 중 어느 것도로 대체 할 수 없습니다 .