Folgender Code, ich suche ein Element in einer Liste, das einen bestimmten Namen trägt:
Code: Alles auswählen
T * Find( String const & identifier ) const
{
if( identifier.IsNotNull() )
for( T * temp = static_cast<T *>( List<T>::First ); temp; temp = (T*) temp->BaseNode<T>::Succ )
if( identifier == temp->GetIdentifier() ) )
return temp;
return NULL;
}
Code: Alles auswählen
inline bool operator == ( XSD::String::String const & lhs, XSD::String::String const & rhs )
Trotzdem ist die Bedingung if( identifier == temp->NodeIdentifier::GetIdentifier() ) ) immer wahr, ich finde also immer das erste Element oder keins.
Um sicher zu stellen, dass hier wirklich Strings verglichen werden, schließlich gibt es einen eindeutigen Operator dafür, sorge ich dafür, dass es keine falsche Überladung von GetIdentifier() geben darf:
Code: Alles auswählen
if( identifier == temp->NodeIdentifier::GetIdentifier() ) )
Code: Alles auswählen
T * Find( String const & identifier ) const
{
if( identifier.IsNotNull() )
for( T * temp = static_cast<T *>( List<T>::First ); temp; temp = (T*) temp->BaseNode<T>::Succ )
{
String const & rhs = temp->NodeIdentifier::GetIdentifier();
if( identifier == rhs ) )
return temp;
}
return NULL;
}
Ich nehme also die den operator bool() für die Strings wieder raus und erhalte folgende Fehlermeldung:
Code: Alles auswählen
c:\users\xin\desktop\genesys\trunk\de\xsd\util\list.h(548) : error C2665: "XSD::Util::operator ==": Durch keine der 2 Überladungen konnten alle Argumenttypen konvertiert werden.
c:\users\xin\desktop\genesys\trunk\de\xsd\util\tagged.h(13): kann 'bool XSD::Util::operator ==(XSD::Util::TagType,XSD::Util::TagType)' sein
c:\users\xin\desktop\genesys\trunk\de\xsd\util\tagged.h(55): oder "bool XSD::Util::operator ==(XSD::Util::TagSave,XSD::Util::TagSave)"
bei Anpassung der Argumentliste '(const XSD::String::String, const XSD::String::String)'
c:\users\xin\desktop\genesys\trunk\de\xsd\util\list.h(542): Bei der Kompilierung der Klassen-template der XSD::Util::XMLBaseNode *XSD::Util::NamedList<T>::Find(const XSD::String::String &) const-Memberfunktion
with
[
T=XSD::Util::XMLBaseNode
]
c:\users\xin\desktop\genesys\trunk\de\xsd\util\xml.h(125): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "XSD::Util::NamedList<T>".
with
[
T=XSD::Util::XMLBaseNode
]
Visual C++ blendet Operatoren in höher gelegenen Namensräumen aus. Also findet er keinen und beginnt implizit und ohne Warning zum Erstbesten zu konvertieren, was ihm einfällt: bool, obwohl ein Operator existiert, dessen Signatur 100%ig passt - nur halt nicht im aktuellen Namensraum.
Ausgeblendet wurden die globalen 'operator ==', weil ich versehentlich die Operatoren für TagType und TagSave nicht global gesetzt habe.
Da man bei einen Operator in Kurzschreibweise selbst nicht wählen kann, aus welchem Namensraum er kommen soll ('if( identifier ::== rhs )'), muss man die lange Schreibweise wählen:
Code: Alles auswählen
T * Find( String const & identifier ) const
{
if( identifier.IsNotNull() )
for( T * temp = static_cast<T *>( List<T>::First ); temp; temp = (T*) temp->BaseNode<T>::Succ )
{
String const & rhs = temp->NodeIdentifier::GetIdentifier();
if( ::operator ==( identifier, rhs ) )
return temp;
}
return NULL;
}
Um den Operator == in den jeweiligen Namensraum zu holen, wäre ein using operator ==; erforderlich gewesen. Sogesehen macht der Visual C++ hier alles richtig. Hilfreich ist es aber dennoch nicht, zumindest eine Warning 'Ich weiß, was Du diesen Sommer nicht tun wolltest' wäre nicht ganz schlecht gewesen. Auch die kommentarlose, implizite Konvertierung von gleich zwei Parametern halte ich für leicht fragwürdig.
Die letzte Version funktioniert jetzt, wie gewünscht. Ich baue jetzt die beiden versehentlich nicht globalen operatoren um, so dass sie global und damit gleichberechtigt stehen.
Und die Moral aus der G'schicht: operatoren in Namensräumen nutzt man nicht... (das steht glaube ich auch bei Scott Meyers, aber war ja auch hier nicht beabsichtigt ^^)