Frage

Eigentlich habe ich ein Problem mit etwas Bibliothek mit Intel-Compiler kompiliert wird.

Die gleiche Bibliothek wurde ordnungsgemäß mit g ++ kompiliert.

Problem wird durch Vorlagen verursacht. Was ich möchte, verstehen, ist die Erklärung von **typename** als nicht Template-Funktion Parameter und Variablendeklaration innerhalb Funktionskörper

Beispiel:

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

Compilation diese Art von Code produzieren folgende Fehler (Intel), (gcc behauptet nicht): Ich habe folgende Fehler bekam

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

Was ich möchte, verstehen, ist die Verwendung des Typnamen im Innern des Körpers von Funktionen, Parameterdeklarationen.

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

in verschiedener Datei Ich habe:

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;**
War es hilfreich?

Lösung

Sie müssen typename verwenden, um so genannte „abhängige Typen“. Das sind Typen, die auf einer Vorlage Argument abhängen und sind nicht bekannt, bis die Vorlage instanziiert wird. Es ist wahrscheinlich am besten erklärt anhand eines Beispiels:

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

Die typedef definiert barbar ist eine, die ein typename benötigt, um für die Compiler in der Lage sein, um die Vorlage zu prüfen eklatante syntaktische Fehler vor es ist mit einem konkreten Typ instanziiert. Der Grund dafür ist, dass, wenn der Compiler die Vorlage zum ersten Mal sieht (wenn es nicht mit konkretem Template-Parameter noch instanziiert), der Compiler nicht weiß, ob Foo::bar ein Typ ist. Für alle es wissen, ich könnte Absicht baz mit Typen wie diese auszuprägen

struct some_other_foo {
  static int bar;
};

In diesem Fall Foo::bar zu einem Objekt verweist , keinen Typ, und die Definition von baz::bar würde syntaktischer Unsinn. Ohne zu wissen, ob Foo::bar auf eine Art bezieht, hat der Compiler keine Chance etwas innerhalb baz zu überprüfen, die direkt oder indirekt sind barbar mit selbst für die dümmste Fehler bis baz instanziiert wird. Mit Hilfe der richtigen typename, baz sieht wie folgt aus:

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

  barbar f();

  // more stuff...
};

Jetzt ist der Compiler auf weiß wenigstens, dass Foo::bar soll der Name einer Art sein, die barbar ein Typname auch macht. So ist die Erklärung von f() ist syntaktische auch OK.

Übrigens gibt es ein ähnliches Problem mit Vorlagen statt Typen:

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

Wenn der Compiler „sieht“ Foo::bar es nicht weiß, was es ist, so bar<Foo könnte genausogut ein Vergleich sein, den Compiler verwirrt über den Hinter > verlassen. Auch hier müssen Sie den Compiler einen Hinweis geben, dass Foo::bar soll der Name einer Vorlage sein:

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

Achtung: Bemerkenswerter Visual C ++ weiterhin nicht implementieren richtigen zweiphasige Lookup (im Wesentlichen: sie nicht wirklich Vorlagen überprüfen, bis sie instanziiert werden). Dafür ist es akzeptiert oft fehlerhaften Code, der ein typename oder ein template vermisst.

Andere Tipps

Der Punkt des typename Schlüsselwort ist, den Compiler zu sagen, dass etwas ein Typname ist, in Situationen, in denen es nicht offensichtlich ist. Nehmen Sie dieses Beispiel:

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

Ist T::foo ein Typ, was bedeutet, wir einen Zeiger deklarieren, oder ist T::foo eine statische Variable, und wir eine Multiplikation tun?

Da die Compiler keine Ahnung von dem, was T zu der Zeit sein, könnte es die Vorlage liest, sie keine Ahnung hat, welche die beiden Fälle korrekt ist.

Der Standard schreibt vor, dass der Compiler den letzteren Fall übernehmen sollte, und nur T::foo als Typnamen interpretieren, wenn es durch das typename Schlüsselwort, wie dies vorangestellt ist:

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

Bei Ihrem Code:

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

Wenn der obige Code nicht ein Teil einer Vorlage ist, dann kann es nicht g kompiliert werden ++ verwenden, es sei denn, die alte Version von g ++.

Wie meine Erfahrung, FC9 oder GNU C / ++ Version 4.2x es als Fehler berichten, wird es beklagen:

typename only can be used in template code

während FC8 oder GNU C / ++ 4.1x möglicherweise nicht.

Bitte beachten Sie

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

für weitere Vorlage und Typnamen Beispiele.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top