Pergunta

Estou tentando definir classe base, que contém typedef só.

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

Por que em B I receber um erro que Vec_t não é reconhecido e eu preciso escrevê-lo explicitamente?

typename A<T>::Vec_t v;
Foi útil?

Solução

Eu acredito que esta questão é duplicado, mas não posso encontrá-lo agora. C ++ Padrão diz que você deve qualificar totalmente nome de acordo com 14.6.2 / 3:

Na definição de um modelo de classe ou um membro de um modelo de classe, se uma classe base do modelo de classe depende de um parâmetro-molde, o âmbito classe base é não examinada durante nome não qualificado pesquisa quer no ponto de definição do modelo de classe ou membro ou durante uma instanciação do modelo de classe ou membro.

UPD: eu encontrei duplicar finalmente: aqui é .

Outras dicas

Existe algo chamado dependente e nondependent nomes em caso de modelos.

Se o nome depende do modelo parâmetro T a sua dependente nome e outros aqueles não dependem de parâmetro T são independente nomes.

Aqui está a regra: o compilador não olhar em classes base dependentes (como A) quando se olha-se nondependent nomes (como Vec_t). Como um resultado, o compilador não sabe que eles mesmo existem muito menos são tipos.

Compiler não pode assumir que Vec_t é um tipo até que ele sabe T porque não há uma especialização potencial de A<T> onde A<T>:: Vec_t é um é um membro de dados

Portanto, a solução é o uso typename

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

Eu recomendo que você passar por este https://isocpp.org/ wiki / FAQ / templates # nondependent-name-pesquisa-tipos .

Old (quebrado) link: http: // www. parashift.com/c++-faq-lite/templates.html#faq-35.18

Como o compilador não é certo que os nomes Vec_t um tipo. Por exemplo, A<T> pode ser especializado para T=int a não tem que typedef particular.

Para completar, aqui está como você poderia atenuar esse incômodo um pouco, ou:

  • re-typedef esses tipos de classes derivadas, ou melhor - como com métodos -
  • apenas importar esses nomes no âmbito classe derivada com uma 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;
};

Pode ser útil se você tiver mais de uma menção do typedef herdadas na classe derivada. Além disso, você não precisa adicionar typename cada vez com isso.

Você precisa qualificar explicitamente o uso de Vec_t porque o compilador não sabe onde Vec_t vem.

Ele não pode assumir qualquer coisa sobre a estrutura de um, já que o modelo de classe A pode ser especializado. A especialização pode incluir uma Vec_t que não é um typedef, ou até pode não incluir um Vec_t membro em tudo.

Vec_t não é um nome dependente, e o compilador precisa saber o que é sem instanciar todos os modelos (classe base, neste caso). Ele não é realmente diferente de:

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

Aqui bem as necessidades do compilador para saber sobre std :: string, mesmo que X não é instanciado, uma vez que o nome não depende do argumento modelo T (tanto quanto o compilador pode assumir).

Ao todo, typedefs em uma classe base modelo parece bastante inútil para uso na classe derivada. Os typedefs são úteis para o usuário, no entanto.

Este conceito pode ser associado com a forma como usamos std::vector<T>. Por exemplo, se temos um std::vector<int> Foo. Agora, nós decidir usar qualquer um dos tipos é membro, digamos que um iterator. Neste cenário que explicitamente mencionar

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

Da mesma forma, no seu caso, a fim de usar um tipo de membro público Vec_t de template <typename T> class A, você precisa declará-la explicitamente como

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top