Programing

'템플릿'에 대한 기반에서 파생 클래스로 'typedef'전파

lottogame 2020. 12. 5. 09:09
반응형

'템플릿'에 대한 기반에서 파생 클래스로 'typedef'전파


typedef 만 포함하는 기본 클래스를 정의하려고합니다.

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
private:
    Vec_t v;  // fails - Vec_t is not recognized
};

BI에서 Vec_t가 인식되지 않고 명시 적으로 작성해야한다는 오류가 발생하는 이유는 무엇입니까?

typename A<T>::Vec_t v;

이 질문이 중복 된 것 같지만 지금은 찾을 수 없습니다. C ++ Standard는 14.6.2 / 3에 따라 이름을 정규화해야한다고 말합니다.

클래스 템플릿 또는 클래스 템플릿의 멤버 정의에서 클래스 템플릿의 기본 클래스가 template-parameter에 의존하는 경우 클래스 정의 시점에서 정규화되지 않은 이름 조회 중에 기본 클래스 범위가 검사되지 않습니다. 템플릿 또는 멤버 또는 클래스 템플릿 또는 멤버의 인스턴스화 중에.

UPD : 마침내 중복을 찾았습니다. 여기 있습니다 .


템플릿의 경우 종속 및 종속 이름 이라는 것이 있습니다 .

이름이 템플릿 매개 변수 T에 종속 된 경우 해당 종속 이름과 매개 변수 T에 종속 되지 않는 다른 이름 독립된 이름입니다.

규칙은 다음과 같습니다. 컴파일러는 비 종속 이름 (예 : Vec_t)을 찾을 때 종속 기본 클래스 (예 : A)를 찾지 않습니다. 결과적으로 컴파일러는 유형은 고사하고 존재조차 알지 못합니다.

어디가 데이터 멤버 인지에 대한 잠재적 전문화 Vec_tT있기 때문에 컴파일러는 알 때까지 유형 이라고 가정 할 수 없습니다.A<T>A<T>:: Vec_t

그래서 해결책은 typename을 사용하는 것입니다.

 typename A<T>::Vec_t v;  ← good

https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types 를 살펴 보는 것이 좋습니다 .

이전 (깨진) 링크 : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18


컴파일러 Vec_t는 유형의 이름을 확실하지 않기 때문 입니다. 예를 들어, A<T>대한 전문 수 있습니다 T=int없는 특정 있습니다 typedef.


완전성을 위해 다음과 같이 이러한 성가신 문제를 완화 할 수있는 방법이 있습니다.

  • 파생 클래스에서 해당 유형을 다시 typedef하거나 메소드와 마찬가지로 더 좋습니다.
  • 다음과 같이 파생 클래스 범위에서 해당 이름을 가져옵니다 using declaration.

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

private:
    Vec_t v;
};

typedef파생 클래스에서 상속 된 항목 대해 둘 이상의 언급이있는 경우 유용 할 수 있습니다 . 또한 typename매번 추가 할 필요가 없습니다 .


Vec_t컴파일러가 어디에서 Vec_t오는지 알지 못하기 때문에 의 사용을 명시 적으로 한정해야합니다 .

It cannot assume anything about the structure of A, since the class template A may be specialized. The specialization may include a Vec_t which is not a typedef, or it may not even include a member Vec_t at all.


Vec_t is not a dependent name, and the compiler needs to know what it is without instantiating any templates (base class in this case). It is really no different from:

template <class T>
class X
{
    std::string s;
}

Here as well the compiler needs to know about std::string even if X is not instantiated, since the name does not depend on the template argument T (as far as the compiler can assume).

All in all, typedefs in a template base class seem rather useless for use in derived class. The typedefs are useful for the user, however.


This concept can be associated with how we use std::vector<T>. For example, if we have a std::vector<int> Foo. Now, we decide to use any of it's member types, lets say an iterator. In this scenario we explicitly mention

std::vector<int>::iterator foo_iterator;

Similarly in your case, in order to use a public member type Vec_t of template <typename T> class A, you need to explicitly declare it as

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;

참고URL : https://stackoverflow.com/questions/1643035/propagating-typedef-from-based-to-derived-class-for-template

반응형