Pergunta

Na verdade, eu tenho um problema com a compilação de alguma biblioteca com o compilador Intel.

Esta mesma biblioteca foi compilada corretamente com g ++.

O problema é causado por modelos. O que eu gostaria de entender é a declaração de **typename** como não template parâmetro de função e declaração variável dentro do corpo da função

exemplo:

void func(typename sometype){..
...
typename some_other_type;
..
}

Compilation este tipo de produto código a seguir erros (Intel), (gcc não reivindica a): Eu tenho seguinte erros

../../../libs/log/src/attribute_set.cpp(415): error: no operator "!=" matches these operands
            operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
      while (begin != end)
                   ^
          detected during instantiation of "void boost::log_st::basic_attribute_set<CharT>::erase(boost::log_st::basic_attribute_set<CharT>::iter<'\000'>, boost::log_st::basic_attribute_set<CharT>::iter<'\000'>) [with CharT=wchar_t]" at line 438

../../../boost/log/attributes/attribute_set.hpp(115): error: no operator "!=" matches these operands
            operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
              if (it != m_pContainer->end())

O que eu gostaria de entender é o uso do typename dentro do corpo de funções, declarações de parâmetro.

ex:.

template< typename CharT >
struct basic_attribute_values_view< CharT >::implementation
{

public:
..
..
void adopt_nodes( **typename attribu**te_set_type::const_iterator& it, **typename attribut**e_set_type::const_iterator end)
    {
        for (; it != end; ++it)
            push_back(it->first, it->second.get());
    }

no arquivo diferente eu tenho:

template< typename CharT >
class basic_attribute_set
{
    friend class basic_attribute_values_view< CharT >;

    //! Self type
    typedef basic_attribute_set< CharT > this_type;

public:
    //! Character type
    typedef CharT char_type;
    //! String type
    typedef std::basic_string< char_type > string_type;
    //! Key type
    typedef basic_slim_string< char_type > key_type;
    //! Mapped attribute type
    typedef shared_ptr< attribute > mapped_type;

    //! Value type
    typedef std::pair< const key_type, mapped_type > value_type;
    //! Allocator type
    typedef std::allocator< value_type > allocator_type;
    //! Reference type
    **typedef typename allocator_type::reference reference;**
Foi útil?

Solução

Você precisa usar typename para os chamados "tipos dependentes". Esses são os tipos que dependem de um argumento de modelo e não são conhecidos até que o modelo é instanciado. É provavelmente melhor explicado usando um exemplo:

struct some_foo {
  typedef int bar;
};

template< typename Foo >
struct baz {
  typedef Foo::bar barbar; // wrong, shouldn't compile

  barbar f(); // would be fine if barbar were a type

  // more stuff...
};

Isso typedef definir barbar é aquele que exige um typename para que o compilador para ser capaz de verificar o modelo para erros sintácticos flagrantes antes é instanciado com um tipo concreto. A razão é que, quando o compilador vê o modelo pela primeira vez (quando não é instanciado com parâmetros do modelo concreto ainda), o compilador não sabe se Foo::bar é um tipo. Por tudo o que sabe, eu poderia baz intenção de ser instanciado com tipos como este

struct some_other_foo {
  static int bar;
};

caso em que Foo::bar remete a um objeto , e não um tipo, ea definição de baz::bar seria absurdo sintática. Sem saber se Foo::bar refere-se a um tipo, o compilador não tem nenhuma possibilidade de verificar qualquer coisa dentro baz que está direta ou indiretamente usando barbar mesmo para os mais erros estúpidos até baz é instanciado. Usando o typename adequada, baz esta aparência:

template< typename Foo >
struct baz {
  typedef typename Foo::bar barbar;

  barbar f();

  // more stuff...
};

Agora, o compilador pelo menos sabe que Foo::bar é suposto ser o nome de um tipo, o que torna barbar um nome de tipo, também. Assim, a declaração de f() é sintática OK, também.

A propósito, há um problema semelhante com modelos em vez de tipos:

template< typename Foo >
struct baz {
  Foo::bar<Foo> create_wrgl(); // wrong, shouldn't compile
};

Quando o compilador "vê" Foo::bar ele não sabe o que é, por isso bar<Foo poderia muito bem ser uma comparação, deixando o compilador confuso sobre o > final. Aqui, também, você precisa dar o compilador uma dica que Foo::bar é suposto ser o nome de um modelo:

template< typename Foo >
struct baz {
  Foo::template bar<Foo> create_wrgl();
};

Cuidado: Notavelmente Visual C ++ continua a não implementar a pesquisa de duas fases apropriado (em essência: ele realmente não se verifique modelos até que sejam instanciado). Mesmos que muitas vezes aceita código errônea de que perde uma typename ou um template.

Outras dicas

O ponto da palavra-chave typename é para dizer ao compilador que algo é uma typename, em situações em que não é óbvio. Veja este exemplo:

template<typename T>
void f()
{
    T::foo * x;
}

É T::foo um tipo, ou seja, estamos declarando um ponteiro, ou é T::foo uma variável estática, e estamos fazendo uma multiplicação?

Uma vez que o compilador não tem idéia do que T pode ser no momento em que lê o modelo, ele não tem idéia de qual dos dois casos está correto.

Os ditames padrão que o compilador deve assumir último caso, e somente interpretar T::foo como um typename se for precedido pela palavra-chave typename, como este:

template<typename T>
void f()
{
    typename T::foo* x; //Definitely a pointer.
}

Ao seu código:

void func(typename sometype)
{
    .....typename some_other_type;
    ..
}

Se o código acima não é uma parte de um modelo, então não pode ser compilado usando g ++, a menos que a versão antiga do g ++.

Como o meu experiente, FC9 ou GNU C / ++ versão 4.2 x irá relatá-lo como um erro, ele vai reclamar:

typename only can be used in template code

enquanto FC8 ou GNU C / ++ 4.1x não pode.

Por favor, veja

http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/ringed_inl.h
and 
http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/cont_inl.h

Para obter mais exemplos de modelos e TypeName.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top