템플릿에서 키워드 'typename'과 'class'의 차이점은 무엇입니까?


504

템플릿의 경우 두 선언을 모두 보았습니다.

template < typename T >
template < class T >

차이점이 뭐야?

다음 예제에서 이러한 키워드의 의미는 정확히 무엇입니까 (템플릿에 대한 독일 위키 백과 기사에서 발췌)

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

답변:


430

typenameclass템플릿을 지정의 기본 경우 교환 할 수있다 :

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>;

필자가 놓친 다른 사례가 있다고 확신하지만 결론은 다음과 같습니다.이 두 키워드는 동일하지 않으며 하나를 사용해야하는 일반적인 경우입니다.


45
마지막 것은 클래스를 정의하기 위해 typename이 아닌 클래스 또는 구조체를 사용해야한다는 사실의 특별한 경우입니다. template <typename T> typename Foo {};Foo <T>는 클래스이므로 클래스 의 처음 두 비트 중 어느 것도로 대체 할 수 없습니다 .
Steve Jessop

2
std::vector<int>::value_type종속 유형이 아니므로 필요하지 않습니다 typename. 유형이 템플리트 매개 변수에 의존하는 경우에만 필요합니다.template<class T> struct C { typedef typename std::vector<T>::value_type type; };
Georg Fritzsche

2
그리고 다시, param_t종속 유형이 아닙니다. 종속 유형은 템플릿 매개 변수에 따라 달라집니다 이름 예를 들면 foo<param_t>::some_type,하지 템플릿 매개 변수 자신을.
Georg Fritzsche

2
C ++ 1z 제안 N4051 을 사용하면 typename, 즉 을 사용할 수 있습니다 template <typename> typename C.
user4112979

4
현재 GCC 5, G ++ 이제 템플릿 템플릿 매개 변수에 유형 이름을 수 있습니다 .
Chnossos

95

템플릿 매개 변수를 명명 typenameclass동일합니다. §14.1.2 :

template-parameter에서 class와 typename 사이에는 의미 상 차이가 없습니다.

typename그러나 템플릿을 사용할 때 다른 컨텍스트에서 컴파일러가 종속 유형을 참조하고 있음을 암시 할 수 있습니다. §14.6.2 :

템플리트 선언 또는 정의에 사용되며 템플리트 매개 변수에 종속 된 이름은 적용 가능한 이름 검색에서 유형 이름을 찾거나 이름이 키워드 typename에 의해 규정되지 않는 한 유형의 이름을 지정하지 않는 것으로 간주됩니다.

예:

typename some_template<T>::some_type

typename컴파일러가 없으면 일반적으로 유형을 참조하는지 여부를 알 수 없습니다.


2
규칙을 이해하지만 컴파일러가 some_template <T>을 내부적으로 유형으로 취급하지 못하게하는 이유는 무엇입니까? 내가 분명한 것을 놓친다면 죄송합니다.
batbrat

23

기술적 인 차이는 없지만 두 가지가 약간 다른 것을 나타내는 데 사용되었습니다.

내장 (예 : 배열)을 포함하여 모든 유형을 T로 수락 해야하는 템플릿

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

T가 실제 클래스 인 경우에만 작동하는 템플릿

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

그러나 이것은 일부 사람들이 사용하는 스타일입니다. 표준에 의해 요구되거나 컴파일러에 의해 강제되지 않음


15
나는 당신이 그것을 언급 한 것에 대해 당신을 비난하지는 않지만, 프로그래머들은 중요하지 않은 무언가 ( "내가 올바른 것을 사용 했는가?")에 대해 생각하는 데 시간이 걸리기 때문에이 정책은 꽤 잘못된 지침이라고 생각합니다. 중요 ( "이 템플릿 매개 변수에 필요한 인터페이스를 구현하는 내장 유형이 있습니까?"). 템플릿 매개 변수의 모든 멤버는 (사용되는 경우 T t; int i = t.toInt();다음) 당신은 "진짜 클래스"를해야하고, 사용자가 제공하는 경우 코드는 컴파일되지 않습니다 int에 대한 T...
스티브 Jessop

1
실제 클래스로의 사용을 제한하려면 비 클래스 유형의 오류를 발생 / 발생시키는 특수화를 추가하는 것이 좋습니다. 특정 클래스로의 사용을 제한하려면 해당 클래스 만 전문화하십시오. 어쨌든, 그러한 문체 적 구별은 메시지를 전달하기에는 너무 미묘합니다.
Potatoswatter

2
그것들은 같은 의미이므로 하나만 사용하십시오. 그렇지 않으면 화요일이 아니라면 인라인 {을 사용하는 것과 같으며 다음 행을 사용하는 {입니다.
Paul Draper

+1 나는 때때로 이것을한다. .. class당신은 아마도 일부 연산자를 지원하는 "가치"를 기대할뿐 아니라, 생성 및 / 또는 할당을 복사 또는 이동시킬뿐 아니라, 특히 멤버 액세스 의미를 지원하는 타입이 필요하다는 것을 암시한다. 선언문을 가장 빨리 살펴보면 예상치 못한 class오류 일 때 매개 변수 에 내장 유형을 제공하는 등의 기대와 낙담을 설정합니다 .
Tony Delroy

템플릿이 모든 클래스에서 작동하지만 내장 유형에서는 작동하지 않는 실제 상황이 어떤 종류인지 이해하고 싶습니다. 예가 있습니까?
lfalin

7
  1. 차이 없음
  2. 템플릿 유형 매개 변수 Container자체는 두 가지 유형 매개 변수 가있는 템플릿입니다.

3
일반적으로 차이가 있습니다.
Hassan Syed

컨테이너가 템플릿으로 지정된 두 매개 변수의 이름도 지정할 수 있습니까? 이 예에서는 이름이 없습니다. 또한이 예제에서는 'class Container'로 작성되었습니다. 대신 'typename Container'로 작성 될 수 있습니까?
Mat

2
@Mat : 예, 검색 할 용어는 템플릿 템플릿 매개 변수 / 인수 입니다. 예 :template<template<class U> class V> struct C {};
Georg Fritzsche

6

이 스 니펫 조각은 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 ++에 추가되었습니다. 일부 프로그래머는 계속 클래스를 독점적으로 사용합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.