call to namespace function

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

call to namespace function

Beitrag von BeRsErKeR »

Folgendes Beispiel:

Code: Alles auswählen

namespace foo
{
void bar(){}
}

int main(int argc, char **argv)
{
bar();
return 0;
}
Ist es normal, dass bar gefunden wird, obwohl ich weder ein using namespace benutze, noch einen namespace voranstelle? Mit dem g++ 4.4.3 funktioniert das jedenfalls und der gdb springt auch wirklich in foo::bar.

Meine Frage ist nun, steht das im Standard drin, dass das möglich ist? Also wenn es nur eine passende Funktion gibt, dass er auch die namespaces durchsucht und diese nutzt? Fände ich ziemlich kacke.

Oder hab ich da vielleicht nen namespace nicht geschlossen? Wobei ich dann eigentlich Compilerfehler erwarten würde. Komischerweise geht eine weitere Funktion nicht, die direkt unter bar deklariert wird. Die findet er nicht ... die hat allerdings auch ein template.
Ohne Input kein Output.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: call to namespace function

Beitrag von Aramis »

Er darf bar nicht finden. Ausser dein Beispiel ist vereinfacht und ADL greift.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: call to namespace function

Beitrag von dot »

Jop. Wenn dein echtes bar einen Parameter eines Typs, der in foo liegt bekommt, dann greift ADL und die Welt ist in Ordnung. Das Beispiel so darf jedenfalls nicht kompilieren. Aber wer weiß was gcc da schon wieder treibt ;)
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

ADL?

Naja bar ist eine friend-Methode eines Types, der in foo liegt. Allerdings kennt er diesen Typ auch nicht, wenn ich den namespace nicht dranschreibe.
Ohne Input kein Output.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: call to namespace function

Beitrag von dot »

Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Danke für die Info. Ok die Funktion bekommt auch einen Parameter der was aus dem namespace enthält. Also wohl ADL. Find ich ehrlich gesagt aber doof. Sollte wenigstens eine Warnung kommen bzw. er sollte das gar nicht machen.
Ohne Input kein Output.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: call to namespace function

Beitrag von dot »

Wenn er das nicht machen würde, dann würd schon das übliche Hello World nichtmehr kompilieren ;)

Ich find ADL ist ein wirklich praktisches Feature von C++.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Wieso sollte er das nicht kompilieren, wenn überall ein std:: vor steht, so wie es sich gehört?
Ohne Input kein Output.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: call to namespace function

Beitrag von dot »

Dann müsste es so aussehen:

Code: Alles auswählen

#include <iostream>

int main()
{
  std::operator <<(std::operator <<(std::cout, "hello, world"), std::endl);
}
Find ich jetzt nicht so berauschend...
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: call to namespace function

Beitrag von Aramis »

Kurz formuliert: er findet den operator << im Hello-World ohne using namespace std; nur weil einer der beiden Operanden (z.b. cout) selber in std lebt.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Ok. Das gilt allerdings nur für strings. Wo wir gerade dabei sind, wieso sind eigentlich die <<-Operatoren für strings global und nicht Teil der stream-Klasse? Das frag ich mich schon eine ganze Weile, zumal die sich auch prima als Klassenmethode implementieren lassen.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: call to namespace function

Beitrag von Krishty »

Weil das Schreiben von Strings in Output-Streams weder ein Implementierungsdetail der String-Klasse ist, noch eins der Output-Stream-Klasse.

Es gibt auch irgendwo einen tollen Artikel, der zeigt, dass std::string mit seinen 80 Methoden ekelhaft überladen ist und man mehr als die Hälfte davon besser außerhalb der Klasse hätte realisieren sollen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Krishty hat geschrieben:Weil das Schreiben von Strings in Output-Streams weder ein Implementierungsdetail der String-Klasse ist, noch eins der Output-Stream-Klasse.
Und wieso ist das Schreiben von int, float und Co ein Implementierungsdetail der Output-Stream-Klasse?
Ohne Input kein Output.
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: call to namespace function

Beitrag von kaiserludi »

Krishty hat geschrieben:Weil das Schreiben von Strings in Output-Streams weder ein Implementierungsdetail der String-Klasse ist, noch eins der Output-Stream-Klasse.
und weil der Operator nicht zwingend Zugriff auf irgendwelche private oder protected Variablen/Methoden einer der beiden Kalssen braucht, sondern wunderbar mit reinem Zugriff auf die public Interfaces der Klassen auskommt und natürlich, weil dank namespaces globale Funktionen nicht mehr das Risiko von Namenskollisionen erhöhen, sofern der Benutzer von der Unart absieht, alles und jeden mit "using namespace" einzubinden.

Habe irgendwo mal den interessanten Satz gelesen:
"Java- und C#-Programmierer werden verwundert sein, aber in C++ ist die objekorientierteste Art der Implementation einer Funktionlität keine Klassenmethode, sondern eine globale Funktion im gleichen Namespace wie die Klass, da sie so nciht mehr Zugriffsrechte bekomtm, als sie auch braucht."
Alles, was an privates rumpfuschen kann, ohne das tatsächlich zu müssen, erhöht nur das Risiko, dass der Wartungsaufwand sich erhöht, weil alles innerhalb der Klasse kreuz und quer auf Sachen zugreift, auf die es gar nicht zugreifen bräuchte. Alles, was nur übers öffentliche Itnerface drauf zugreift, muss nicht angefasst werden, sofern man nur an Implementierungsdetails was dreht und wenn man es doch umbauen muss, dann weiß man auch sofort, dass man anscheinend versehentlich doch das Interface verändert hat (z.B. durch Seitenwirkungen (um in der Diskussion Seiteneffekte/Nebeneffekte/Nebenwirkungen keinen zu bevorzugen ;) ) ).

Hat aber auch Vorteile, alles als Membermethoden von Klassen zu implementieren: So ist das ganze Interface eienr Klasse auch im Header in dieser zu finden und liegt nicht sonst wo verstreut in deinem potentiell rieisigen Namespace rum. Gerade wenn eine Methode oder ein Operator aber genauso gut zu einer anderen Kalsse gehören könnte, man es verstärkt Sinn, darüber nach zu denken, ihn/sie als gloable(n) Operator/Funktion in dem Namespace einzubauen.

Das erklärt dann auch, wieso es bei primitiven Datentypen wie intoder float anders gelöst ist:
Hier stellt sich die Frage nicht, in welcher von beiden Kalssen man es implementiert, in dem primitiven Typ geht nun mal schlecht, ohne, dass man eine Wrapperklasse drumherum aufbaut, die dann aus Performancegründen nicht überall genutzt wird.
Inkonsistent ist das trotzdem irgendwie.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: call to namespace function

Beitrag von Krishty »

Amen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Ich frage mich nur warum der Operator für bestimmte Typen (wohlgemerkt Standardtypen) als Member und für andere global implementiert ist. Das macht für mich keinen Sinn.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: call to namespace function

Beitrag von Krishty »

Auf welche beziehst du dich im Speziellen?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Member:

Code: Alles auswählen

ostream& operator<< (bool val);
ostream& operator<< (short val);
ostream& operator<< (unsigned short val);
ostream& operator<< (int val);
ostream& operator<< (unsigned int val);
ostream& operator<< (long val);
ostream& operator<< (unsigned long val);
ostream& operator<< (float val);
ostream& operator<< (double val);
ostream& operator<< (long double val);
ostream& operator<< (const void* val);
Globale Funktionen:

Code: Alles auswählen

ostream& operator<< (ostream& out, char c );
ostream& operator<< (ostream& out, signed char c );
ostream& operator<< (ostream& out, unsigned char c );
 
ostream& operator<< (ostream& out, const char* s );
ostream& operator<< (ostream& out, const signed char* s );
ostream& operator<< (ostream& out, const unsigned char* s );

Ich denke allerdings ich weiß nun warum dem so ist. Jedenfalls vermute ich das. Und zwar können obige Typen in verschiedenen Formen durch IO Manipulatoren angezeigt werden und das werden dann sicherlich interne streamabhängige Flags (z.B. hex, oct, precision) sein, daher können die <<-Operatoren nicht global sein. Korrigiert mich wenn ich mich irre, klingt allerdings plausibel.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: call to namespace function

Beitrag von Krishty »

Ja, das klingt in der Tat plausibel.

Ich bin auch ein wenig verblüfft, dass char und char const * global sind – ich persönlich hätte vor allem die beiden zu Methoden gemacht und alles andere darauf aufgebaut.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: call to namespace function

Beitrag von BeRsErKeR »

Genau das hatte mich ja verwundert. Allerdings macht es in Hinblick auf die IO Manipulatoren und die ostream Methoden put und write schon Sinn.
Ohne Input kein Output.
Antworten