Question

En fait, j'ai un problème avec la compilation d'une bibliothèque avec le compilateur intel.

Cette même bibliothèque a été compilée correctement avec g ++.

Le problème est causé par les modèles. Ce que j'aimerais comprendre, c’est la déclaration de **typename** comme paramètre de fonction modèle et déclaration de variable dans le corps de la fonction

exemple:

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

La compilation de ce type de code produit les erreurs suivantes (intel), (gcc ne prétend pas): J'ai des erreurs suivantes

../../../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())

Ce que j'aimerais comprendre, c’est l’utilisation du nom de type dans le corps des fonctions, les déclarations de paramètres.

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

dans un fichier différent que j'ai:

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;**
Était-ce utile?

La solution

Vous devez utiliser typename pour les soi-disant " types dépendants & ";. Ce sont des types qui dépendent d'un argument de modèle et ne sont pas connus jusqu'à ce que le modèle soit instancié. Il est probablement mieux expliqué à l'aide d'un exemple:

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

Cette typedef définition barbar nécessite un Foo::bar pour que le compilateur puisse vérifier le modèle à la recherche d'erreurs syntaxiques flagrantes avant avant qu'il ne soit instancié avec un type concret . La raison en est que, lorsque le compilateur voit le modèle pour la première fois (lorsqu'il n'est pas encore instancié avec des paramètres de modèle concrets), il ne sait pas si baz est un type. Pour autant qu’il sache, j’aurais peut-être l'intention baz::bar d'être instanciée avec des types comme celui-ci

struct some_other_foo {
  static int bar;
};

auquel cas f() ferait référence à un objet et non à un type, et la définition de bar<Foo serait un non-sens syntaxique. Sans savoir si > se réfère à un type, le compilateur n'a aucune chance de vérifier dans template ce qui utilise directement ou indirectement <=> pour les typos les plus stupides jusqu'à ce que <=> soit instancié. En utilisant le bon <=> , <=> ressemble à ceci:

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

  barbar f();

  // more stuff...
};

Maintenant, le compilateur sait au moins que <=> est censé être le nom d'un type, ce qui fait de <=> un nom de type également. La déclaration de <=> est donc syntaxique, bien entendu.

À propos, il existe un problème similaire avec les modèles au lieu de types:

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

Quand le compilateur & "verra &"; <=> il ne sait pas ce que c'est, donc <=> pourrait tout aussi bien être une comparaison, laissant le compilateur confus au sujet de la fin <=>. Ici aussi, vous devez indiquer au compilateur que <=> est censé être le nom d'un modèle:

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

Attention: il est à noter que Visual C ++ n'implémente toujours pas la recherche en deux phases appropriée (essentiellement, il ne vérifie pas vraiment les modèles tant qu'ils ne sont pas instanciés). Par conséquent, il accepte souvent un code erroné qui manque un <=> ou un <=>.

Autres conseils

Le mot clé typename a pour objet d'indiquer au compilateur que quelque chose est un nom de type, dans les cas où ce n'est pas évident. Prenons cet exemple:

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

Est-ce que T::foo est un type, ce qui signifie que nous déclarons un pointeur, ou <=> est une variable statique et que nous procédons à une multiplication?

Etant donné que le compilateur n'a aucune idée de ce que T pourrait être au moment où il lit le modèle, il ne sait pas non plus lequel des deux cas est correct.

La norme dicte que le compilateur assume ce dernier cas et interprète uniquement <=> comme un nom de type s'il est précédé du mot clé <=>, comme ceci:

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

Sur votre code:

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

Si le code ci-dessus ne fait pas partie d'un modèle, il ne peut pas être compilé avec g ++, à moins de l'ancienne version de g ++.

Comme mon version expérimentée, FC9 ou GNU C / ++ version 4.2x le signalera comme une erreur, il va se plaindre:

typename only can be used in template code

alors que FC8 ou GNU C / ++ 4.1x ne le peuvent pas.

S'il vous plaît voir

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

pour plus d'exemples de template et typename.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top